天道酬勤,学无止境

特定 C++ 随机数生成的 Clang 性能下降(Clang performance drop for specific C++ random number generation)

问题

使用 C++11 的 random 模块时,我在使用std::mt19937 (32 位和 64 位版本)与uniform_real_distribution (浮点数或双数,无关紧要)时遇到了奇怪的性能下降。 与 g++ 编译相比,它慢了一个数量级以上!

罪魁祸首不仅是 mt 生成器,因为它使用uniform_int_distribution很快。 并且这不是uniform_real_distribution的普遍缺陷,因为它与其他生成器(如default_random_engine一起很快。 只是那个特定的组合出奇地慢。

我对内在函数不是很熟悉,但是 Mersenne Twister 算法或多或少是严格定义的,所以我猜实现上的差异不能解释这种差异? 测量程序如下,但这是我在 64 位 linux 机器上对 clang 3.4 和 gcc 4.8.1 的结果:

gcc 4.8.1
runtime_int_default: 185.6
runtime_int_mt: 179.198
runtime_int_mt_64: 175.195
runtime_float_default: 45.375
runtime_float_mt: 58.144
runtime_float_mt_64: 94.188

clang 3.4
runtime_int_default: 215.096
runtime_int_mt: 201.064
runtime_int_mt_64: 199.836
runtime_float_default: 55.143
runtime_float_mt: 744.072  <--- this and
runtime_float_mt_64: 783.293 <- this is slow

生成它并自己尝试的程序:

#include <iostream>
#include <vector>
#include <chrono>
#include <random>

template< typename T_rng, typename T_dist>
double time_rngs(T_rng& rng, T_dist& dist, int n){
    std::vector< typename T_dist::result_type > vec(n, 0);
    auto t1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < n; ++i)
        vec[i] = dist(rng);
    auto t2 = std::chrono::high_resolution_clock::now();
    auto runtime = std::chrono::duration_cast<std::chrono::microseconds>(t2-t1).count()/1000.0;
    auto sum = vec[0]; //access to avoid compiler skipping
    return runtime;
}

int main(){
    const int n = 10000000;
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::default_random_engine rng_default(seed);
    std::mt19937 rng_mt (seed);
    std::mt19937_64 rng_mt_64 (seed);
    std::uniform_int_distribution<int> dist_int(0,1000);
    std::uniform_real_distribution<float> dist_float(0.0, 1.0);

    // print max values
    std::cout << "rng_default_random.max(): " << rng_default.max() << std::endl;
    std::cout << "rng_mt.max(): " << rng_mt.max() << std::endl;
    std::cout << "rng_mt_64.max(): " << rng_mt_64.max() << std::endl << std::endl;

    std::cout << "runtime_int_default: " << time_rngs(rng_default, dist_int, n) << std::endl;
    std::cout << "runtime_int_mt: " << time_rngs(rng_mt_64, dist_int, n) << std::endl;
    std::cout << "runtime_int_mt_64: " << time_rngs(rng_mt_64, dist_int, n) << std::endl;
    std::cout << "runtime_float_default: " << time_rngs(rng_default, dist_float, n) << std::endl;
    std::cout << "runtime_float_mt: " << time_rngs(rng_mt, dist_float, n) << std::endl;
    std::cout << "runtime_float_mt_64: " << time_rngs(rng_mt_64, dist_float, n) << std::endl;
}

分别通过clang++ -O3 -std=c++11 random.cpp或 g++ 编译。 有任何想法吗?

编辑:最后,Matthieu M. 有一个好主意:罪魁祸首是内联,或者更确切地说是缺乏内联。 增加 clang 内联限制消除了性能损失。 这实际上解决了我遇到的许多性能问题。 谢谢,我学到了一些新东西。

回答1

正如评论中已经指出的那样,问题是由 gcc 内联比 clang 更具侵略性这一事实引起的。 如果我们非常积极地使 clang 内联,效果就会消失:

g++ -O3编译你的代码会产生

runtime_int_default: 3000.32
runtime_int_mt: 3112.11
runtime_int_mt_64: 3069.48
runtime_float_default: 859.14
runtime_float_mt: 1027.05
runtime_float_mt_64: 1777.48

clang++ -O3 -mllvm -inline-threshold=10000收益率

runtime_int_default: 3623.89
runtime_int_mt: 751.484
runtime_int_mt_64: 751.132
runtime_float_default: 1072.53
runtime_float_mt: 968.967
runtime_float_mt_64: 1781.34

显然,clang 现在在int_mt情况下内联 gcc,但所有其他运行时现在都处于相同的数量级。 我在 Fedora 20 64 位上使用了 gcc 4.8.3 和 clang 3.4。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Clang vs GCC - 哪个产生更快的二进制文件? [关闭](Clang vs GCC - which produces faster binaries? [closed])
    问题 关闭。 这个问题是基于意见的。 它目前不接受答案。 想改善这个问题吗? 更新问题,以便通过编辑这篇文章用事实和引文来回答问题。 4年前关闭。 改进这个问题 我目前正在使用 GCC,但我最近发现了 Clang,我正在考虑切换。 不过,有一个决定性因素——它生成的二进制文件的质量(速度、内存占用、可靠性)——如果gcc -O3可以生成一个运行速度提高 1% 的二进制文件,或者 Clang 二进制文件占用更多内存,或者只是由于编译器错误而失败,这是一个交易破坏者。 与GCC相比,Clang具有更好的编译速度和更低的编译时内存占用空间,但是我对最终编译软件的基准测试/比较非常感兴趣-您能指出一些还是描述您的经验? 回答1 以下是我在 GCC 4.7.2 和 Clang 3.2 for C++ 中的一些最新发现,尽管范围很窄。 更新:GCC 4.8.1 v clang 3.3比较下面附加。 更新:附加了 GCC 4.8.2 v clang 3.4 比较。 我维护了一个 OSS 工具,它是为 Linux 构建的,有 GCC 和 Clang,还有微软的 Windows 编译器。 工具 coan 是 C/C++ 源文件和代码行的预处理器和分析器:它的计算配置文件主要是递归下降解析和文件处理。 开发分支(与这些结果相关)目前在大约 90 个文件中包含大约 11K LOC。 现在,它是用 C++
  • x86-64 Linux中不再允许使用32位绝对地址?(32-bit absolute addresses no longer allowed in x86-64 Linux?)
    问题 默认情况下,64位Linux使用小型内存模型,该模型将所有代码和静态数据置于2GB地址限制以下。 这样可以确保您可以使用32位绝对地址。 较旧的gcc版本将32位绝对地址用于静态数组,以节省用于相对地址计算的额外指令。 但是,这不再起作用。 如果我尝试在汇编中创建32位绝对地址,则会收到链接器错误:“在创建共享库时,无法将R_X86_64_32S相对于'.data'进行重定位;请使用-fPIC重新编译”。 当然,此错误消息具有误导性,因为我没有创建共享对象,并且-fPIC没有帮助。 到目前为止,我发现的是:gcc版本4.8.5对静态数组使用32位绝对地址,而gcc版本6.3.0却没有。 版本5可能也不是。 binutils 2.24中的链接器允许使用32位绝对地址,而Verson 2.28则不允许。 更改的结果是必须重新编译旧的库,并且破坏旧的汇编代码。 现在我想问:此更改是何时进行的? 是否记录在某处? 是否有一个链接器选项可以接受32位绝对地址? 回答1 您的发行版使用--enable-default-pie配置了gcc,因此--enable-default-pie它将制作与位置无关的可执行文件(允许可执行文件以及库的ASLR)。 如今,大多数发行版都在这样做。 您实际上是在创建一个共享库:PIE可执行文件有点像使用带有入口点的共享库。 动态链接器已经支持此功能
  • 为什么现代的C ++编译器不优化这样的简单循环? (Clang,MSVC)(Why don't modern C++ compilers optimize away simple loops like this? (Clang, MSVC))
    问题 当我使用Clang( -O3 )或MSVC( /O2 )编译并运行此代码时... #include <stdio.h> #include <time.h> static int const N = 0x8000; int main() { clock_t const start = clock(); for (int i = 0; i < N; ++i) { int a[N]; // Never used outside of this block, but not optimized away for (int j = 0; j < N; ++j) { ++a[j]; // This is undefined behavior (due to possible // signed integer overflow), but Clang doesn't see it } } clock_t const finish = clock(); fprintf(stderr, "%u ms\n", static_cast<unsigned int>((finish - start) * 1000 / CLOCKS_PER_SEC)); return 0; } ...循环并没有得到优化。 此外,无论是锵3.6也不VISUAL C ++ 2013,也不GCC 4.8.1告诉我
  • Swift Beta性能:对数组进行排序(Swift Beta performance: sorting arrays)
    问题 我在Swift Beta中实现一种算法,并注意到性能很差。 深入研究后,我意识到瓶颈之一就是对数组进行排序一样简单。 相关部分在这里: let n = 1000000 var x = [Int](repeating: 0, count: n) for i in 0..<n { x[i] = random() } // start clock here let y = sort(x) // stop clock here 在C ++中,类似的操作在我的计算机上耗时0.06s 。 在Python中,它花费0.6秒(绝招,仅y =整数列表的sorted(x))。 在Swift中,如果使用以下命令进行编译,则需要6s : xcrun swift -O3 -sdk `xcrun --show-sdk-path --sdk macosx` 如果使用以下命令进行编译,则最多需要88s : xcrun swift -O0 -sdk `xcrun --show-sdk-path --sdk macosx` Xcode中具有“发布”与“调试”构建的时序是相似的。 这是怎么了与C ++相比,我可以理解一些性能损失,但与纯Python相比,却不能将性能降低10倍。 编辑:天气注意到,将-O3更改为-Ofast使此代码的运行几乎与C ++版本一样快! 但是, -Ofast改变了语言的语义-在我的测试中
  • Clang C ++ Cross Compiler-从Mac OS X生成Windows可执行文件(Clang C++ Cross Compiler - Generating Windows Executable from Mac OS X)
    问题 我使用Clang编译器在Mac上使用Xcode创建了C ++应用程序。 我想编译我的源文件以创建可以在Windows计算机上运行的可执行文件,但是我无法让Clang生成可执行文件。 这是我尝试过的: clang++ -std=c++11 -stdlib=libc++ -arch x86_64 class1.cpp class2.cpp... -o executable.exe 这将创建一个可执行文件,但是它无法运行(Windows给我一个错误,原因是应用程序为16位-不能理解这一点-无法在64位上运行) clang++ -std=c++11 -stdlib=libc++ -target i386-pc-win32 class1.cpp class2.cpp 由于某种原因,每当我使用-target标志时,都会收到一条错误消息,指出编译器无法找到<iostream>标头,但是在其他任何时候它都不会抱怨。 我尝试使用-Ipath/to/iostreamfolder/但这不会产生任何更好的结果 任何建议将是巨大的! 谢谢! 我也尝试过'-triple x86-pc-win32'标志,但是我收到以下警告提示clang: warning: argument unused during compilation: '-triple x86-pc-win32' 回答1
  • Clang 可以用 GCC 编译的 .a 库编译代码吗?(Can Clang compile code with GCC compiled .a libs?)
    问题 我的项目目前正在 gcc 下编译。 它使用 Boost、ZeroMQ 作为静态.a库和一些.so库,如 SDL。 我想一直去叮当声,但不是现在。 我想知道是否可以编译使用在 gcc 下用 clang 编译的.a和.so库的代码? 回答1 是的,您通常可以将clang与 GCC 编译库一起使用(反之亦然,将gcc与 CLANG 编译库一起使用),因为实际上它不是编译,而是相关的链接。 你可能不走运,得到不愉快的惊喜。 原则上,您可以对用于链接相关库的libstdc++版本有一些依赖性(如果它们是用 C++ 编码的)。 实际上,这通常无关紧要。 在 C++ 中,名称修饰理论上可能是一个问题(可能存在一些极端情况,甚至两个不同版本的g++之间不兼容)。 同样,在实践中这通常不是问题。 所以通常你可以将 CLANG(甚至是不同但接近的版本)与 GCC 混合使用,但你可能会有不愉快的惊喜。 任何 C++ 编译器(无论是 CLANG 还是 GCC)都应该能够使用相同的编译器和版本(包括相同的 C++ 标准库实现)编译和链接整个软件(和所有库)并将其链接在一起. 这就是为什么在发行版中升级编译器需要大量工作的原因:发行版制造商必须确保所有软件包都能很好地编译(而且他们确实会得到惊喜!)。 请注意 libstdc++ 的版本确实很重要。 Clang 和 GCC 社区都在努力使其 ABI
  • Clang performance drop for specific C++ random number generation
    Using C++11's random module, I encountered an odd performance drop when using std::mt19937 (32 and 64bit versions) in combination with a uniform_real_distribution (float or double, doesn't matter). Compared to a g++ compile, it's more than an order of magnitude slower! The culprit isn't just the mt generator, as it's fast with a uniform_int_distribution. And it isn't a general flaw in the uniform_real_distribution since that's fast with other generators like default_random_engine. Just that specific combination is oddly slow. I'm not very familiar with the intrinsics, but the Mersenne Twister
  • C ++强制编译时错误/警告开关隐式掉线(C++ Force compile-time error/warning on implicit fall-through in switch)
    问题 switch语句可能非常有用,但会导致程序员忘记break语句的常见错误: switch(val) { case 0: foo(); break; case 1: bar(); // oops case 2: baz(); break; default: roomba(); } 您不会明显收到警告,因为有时明确需要落空。 良好的编码风格建议您在故意犯规时发表评论,但有时这还不够。 我很确定这个问题的答案是否定的,但是:如果您的case确实case ,目前(或将来提出)是否有任何方法能够要求编译器抛出错误(或至少发出警告!)至少没有break; 或// fallthru的效果? 有一个使用switch语句的防御性编程选项会很好。 回答1 好吧,clang具有-Wimplicit-fallthrough ,我不知道但可以通过-Weverything找到。 因此,对于此代码,它给了我以下警告(实时查看): warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough] case 2: ^ note: insert '[[clang::fallthrough]];' to silence this warning case 2: ^ [[clang::fallthrough]]
  • (缺少)C++11 移动语义的性能改进((Missing) performance improvements with C++11 move semantics)
    问题 我已经写 C++11 代码有一段时间了,还没有对它进行任何基准测试,只希望向量操作之类的东西现在通过移动语义“更快”。 因此,当实际使用 GCC 4.7.2 和 clang 3.0(Ubuntu 12.10 64 位上的默认编译器)进行基准测试时,我得到了非常不令人满意的结果。 这是我的测试代码: 编辑:关于@DeadMG 和@ronag 发布的(好的)答案,我将元素类型从std::string更改为没有swap() my::string ,并使所有内部字符串变大(200 -700 字节),这样他们就不会成为 SSO 的受害者。 EDIT2: COW 是原因。 通过伟大的评论再次改编代码,将存储从std::string更改为std::vector<char>并省略复制/移动构造函数(让编译器生成它们)。 没有COW,速度差异其实很大。 EDIT3:使用-DCOW编译时重新添加了以前的解决方案。 这使得内部存储成为std::string而不是 @chico 请求的std::vector<char> 。 #include <string> #include <vector> #include <fstream> #include <iostream> #include <algorithm> #include <functional> static std::size_t dec
  • C ++标准是否允许未初始化的bool导致程序崩溃?(Does the C++ standard allow for an uninitialized bool to crash a program?)
    问题 我知道C ++中的“未定义行为”几乎可以使编译器执行其想要的任何操作。 但是,由于我以为代码足够安全,所以发生了一次崩溃,这让我感到惊讶。 在这种情况下,真正的问题仅在使用特定编译器的特定平台上发生,并且仅在启用优化后才发生。 为了重现此问题并将其简化到最大程度,我尝试了几件事。 这是一个名为Serialize的函数的摘录,该函数将带有bool参数,并将字符串true或false复制到现有的目标缓冲区。 此功能是否在代码审查中,如果bool参数是未初始化的值,实际上没有办法告诉它崩溃吗? // Zero-filled global buffer of 16 characters char destBuffer[16]; void Serialize(bool boolValue) { // Determine which string to print based on boolValue const char* whichString = boolValue ? "true" : "false"; // Compute the length of the string we selected const size_t len = strlen(whichString); // Copy string into destination buffer, which is
  • 是否可以从 VS 插件访问 VC++ 代码 DOM?(Is the VC++ code DOM accessible from VS addons?)
    问题 Visual Studio IntelliSense for VC++ 包括“完整的”EDG C++ 解析器(也被 Intel 和其他公司使用)。 由于插件可以访问 C# 代码 DOM(如果我错了,请纠正我),C++ 代码 DOM 是否也可以访问? 这能用来分析VS环境中打开的VC ++项目? 回答1 Visual C++ 重构扩展能够在项目范围内重命名成员。 它由 MS 构建,但显然他们使用内部 Code DOM 来实现这一点。 所以这是可能的,我只是不知道如何。 CppLister 扩展能够读取由 VS 创建的智能感知数据库,以列出类中的各种成员。 您始终可以使用开源 Clang C++ 解析器(实际上是编译器)并将 AST 读入 C# 对象模型。 有关 C# 与 Clang 的绑定,请参阅 CppSharp 和 ClangSharp。 回答2 我不确定“C++ 代码 DOM”是什么,如果它存在的话。 重要的是 MSVS 使用 EDG 前端来解析和确定符号的含义,以支持 MSVS IDE 操作。 EDG IIRC 构建自己的内部数据结构来表示程序; 我没有理由相信这些数据结构是“C++ 代码 DOM”,或者您可以看到它们,或者您可以在 MSDN 上找到它们。 您真正提出的问题是您想分析 C++ 源代码。 我同意,拥有 EDG 前端信息将是实现这一目标的重要帮助;
  • LLVM项目的目录布局介绍
    LLVM项目的目录布局介绍 从git获取llvm项目的源码方式: git clone https://github.com/llvm/llvm-project.git 我使用的版本分支是:llvmorg-9.0.0 下载源码后,进入llvm-project目录包括如下内容: 接下来将对llvm-project中每个目录的其内容做简介 llvm-project/clang Clang是一个基于llvm上的编译器前端,支持编译的高级语言有C/C++/Objective-C等,它拥有惊人的快速编译代码的能力(如,在Debug下编译Objective-C"比GCC快大约3倍")。Clang为用户提供更加友好和清晰有用的报错/警告信息,同时提供了一个用于构建出色的源代码级工具的平台。例如,将Clang作为库构建的工具——Clang静态分析器,它是一种可自动查找代码bug的工具。 llvm-project/clang-tools-extra clang-tools-extra作为LLVM和Clang基础架构项目的一部分。这些工具独立开来,以便于更加轻便地检出Clang的核心代码。 如果要将该项目添加到LLVM中构建时,需要将其添加到llvm/tools目录中,并命名为extra。 llvm-project/compiler-rt compiler-rt
  • 使用-fno-rtti在OS X上引发和捕获异常的问题(Problems throwing and catching exceptions on OS X with -fno-rtti)
    问题 这个问题与这个问题有些相似,但是被接受的答案并没有真正提出解决方案或解决方法。 在我们的项目中,我们有一个dylib和主要的可执行文件。 dylib是使用-fno-rtti编译的,而可执行文件确实使用RTTI。 当从dylib抛出异常(例如std::bad_alloc )并被exe捕获时,就会发生问题。 (在您大喊“例外需要RTTI,因此您必须先启用它!”之前,请注意,无论-frtti或-fno-rtti设置如何,总是会生成例外所需的RTTI。这实际上记录在-fno-rtti标志说明。在OS X上的问题是它不是以相同的方式生成的) 经过调查,发现了以下内容: 在dylib( -fno-rtti )中,有异常的RTTI结构的本地副本。 特别是__ZTISt9bad_alloc符号( typeinfo for std::bad_alloc )。 exe( -frtti )从libstdc++.6.dylib导入typeinfo符号,并且没有本地副本 由于异常处理代码依赖于比较typeinfo指针来确定异常匹配,因此匹配失败,只有catch(...)成功。 到目前为止,我看到以下选项: 1)使用-frtti编译所有内容,或者至少编译引发和捕获异常的文件。 这是可行的,但是我不喜欢为所有内容生成RTTI的想法,即使我们不使用它也是如此。 并且带有例外的文件列表很容易过时。 2
  • lang优化级别(Clang optimization levels)
    问题 在gcc上,该手册根据特定的优化参数( -funswitch-loops , -fcompare-elim等)解释了-O3 , -Os等的-fcompare-elim 。 我正在为clang寻找相同的信息。 我在网上和man clang中仅提供了一般性信息( -O2优化了-O1 , -Os提高了速度,...),并且还在Stack Overflow上查找并发现了这一点,但是我没有找到任何相关的信息在引用的源文件中。 编辑:我找到了答案,但是我仍然很感兴趣是否有人链接到用户手册,该手册记录了所有优化过程以及-O x选择的过程。 目前,我仅找到此通行证列表,但在优化级别上却一无所获。 回答1 我发现了这个相关问题。 总结一下,以了解有关编译器优化过程的信息: llvm-as < /dev/null | opt -O3 -disable-output -debug-pass=Arguments 正如Geoff Nixon的答案(+1)中指出的那样, clang还运行了一些更高级别的优化,我们可以使用以下方法进行检索: echo 'int;' | clang -xc -O3 - -o /dev/null -\#\#\# 个人通行证的文件可在此处获得。 对于6.0版,通行证如下: 基线( -O0 ): opt集:-tti -verify -ee-instrument
  • 如何在CentOS 7上通过clang生成libcxx和libcxxabi(How to Build libcxx and libcxxabi by clang on CentOS 7)
    问题 我想在CentOS 7上将C ++ 11或C ++ 14与clang / clang ++一起使用。如何构建此构建环境? 回答1 本文介绍了如何在CentOS 7上构建C ++ 11构建环境:RHEL的EPEL存储库提供Clang程序包,但不提供C ++库程序包。 因此,这些零件很难手工制造。 为Clang定制的C ++库是libc ++(libcxx)[1]。 然后,libcxx还需要一个ABI库libc ++ abi(libcxxabi)[2]。 不幸的是,这两个库都有循环依赖问题。 为了解决循环依赖问题,可以在不链接libc ++ abi的情况下构建libc ++。 然后,使用此libc ++,我们可以构建链接libc ++的libc ++ abi。 最后,使用libc ++ abi,​​我们可以构建链接libc ++ abi的新libc ++。 下面给出了clang,libc ++和libc ++ abi环境构建步骤: 添加RHEL的EPEL存储库。 打开以下链接,找到“如何使用这些额外的软件包?”部分。 https://fedoraproject.org/wiki/EPEL 查找适用于您的CentOS版本的epel软件包。 例如,: sudo rpm -i https://dl.fedoraproject.org/pub/epel/epel-release
  • 在Mac OS X上链接不同的C ++标准库(Link different C++ standard libraries on Mac OS X)
    问题 现在,Mac OS X上可以存在多个C ++标准库,这看起来很混乱。 根据https://stackoverflow.com/a/8457799/1772681的说法,混合libstdc ++和libc ++会导致链接错误,这可以捕获这种危险情况,这是一件好事。 另一方面,仍有2种情况需要更多调查,我在github gist(https://gist.github.com/manphiz/7195515)中为此创建了一些测试用例。 它确认混合使用链接到libstdc ++(来自系统或原始GNU GCC的动态库)和libc ++(系统)的动态库将导致链接错误。 但是,如果一个动态库链接到系统libstdc ++,而另一个动态库链接到香草GNU GCC libstdc ++,然后又将它们链接到二进制文件,则对于我的简单测试用例,它甚至可以在运行时使用。 $ make -f Makefile.system_gnu g++-4.8 -g -Wall -fPIC -o main.o -c main.cc g++-4.8 -g -Wall -fPIC -o test_a.o -c test_a.cc g++-4.8 -dynamiclib -o libtest_a.dylib test_a.o clang++ -g -Wall -fPIC "-stdlib=libstdc++" -o
  • 我们可以通过C ++编译器看到模板实例化的代码吗(Can we see the template instantiated code by C++ compiler)
    问题 有没有办法知道C ++中模板函数或类的编译器实例化代码 假设我有以下代码 template < class T> T add(T a, T b){ return a+b; } 现在,当我打电话 add<int>(10,2); 我想知道编译器为int特定版本创建的函数。 我正在使用G ++,VC ++。 如果有人可以帮助我指出实现此目标的编译器选项,将很有帮助。 希望问题清楚。 提前致谢。 回答1 您绝对可以使用“ -S”选项查看g ++生成的汇编代码。 我认为不可能显示“ C ++”等效模板代码-但我仍然希望g ++开发人员对此有所了解-我不知道gcc的体系结构。 使用汇编时,您可以查看结果代码以查找与您的函数相似的代码。 由于运行gcc -S -O1 {yourcode.cpp},我得到了这个(AMD64,gcc 4.4.4) _Z3addIiET_S0_S0_: .LFB2: .cfi_startproc .cfi_personality 0x3,__gxx_personality_v0 leal (%rsi,%rdi), %eax ret .cfi_endproc 这实际上只是一个int加法(合法)。 现在,如何解码c ++名称mangler? 有一个名为c ++ filt的实用程序,您将规范名称(等效于C的名称)粘贴进去,然后得到等价的demangled c ++
  • 华为:既满足用户体验,又节省功耗的App应用设计开发方法
    高耗电设计场景举例PushPush即notification消息的一个交互,是一种消息推送机制,iOS有唯一的Push通道,所有应用的服务端要与应用交互的消息都必须通过这个Push通道,避免了通知消息唤醒应用。Android则存在多个Push通道,谷歌有GCM;每个厂商也有自己的通道,比如华为Push;除此之外应用有自己的独立通道,如微信。这种情况下就导致应用被频繁唤醒,整个系统其实是没有休眠的,没办法像iOS的通道这样控制行为。Wakelock长时间持锁上图是Android的休眠机制,刚开始的时候系统被频繁的唤醒,在息屏后一段时间会进入浅睡眠,这时网路访问就没有了、Syncs以及Jobs Deferred都不推荐使用,但是定期还是会有一个维护窗口,这段时间应用程序是可以被唤醒的。再持续一段时间后就进入了深度睡眠模式,这时不仅没有网络连接,GPS等也被禁止,这其实是理想的睡眠状态,实际是比较难进入这种状态的。为了不让系统的休眠导致应用进程结束,一般需要设置Wakelock。Wakelock有两种使用形式,一种是采用PowerMananger申请Wakelock锁,这段时间内系统不会进入休眠状态;另一种是直接使用底层的wake_lock或wake_unlock接口来避免系统进入休眠状态。Wakelock持锁如果忘记释放,会导致系统一直被频繁唤醒无法进入浅睡眠而一直处于异常耗电状态
  • 华为:既满足用户体验,又节省功耗的App应用设计开发方法
    高耗电设计场景举例PushPush即notification消息的一个交互,是一种消息推送机制,iOS有唯一的Push通道,所有应用的服务端要与应用交互的消息都必须通过这个Push通道,避免了通知消息唤醒应用。Android则存在多个Push通道,谷歌有GCM;每个厂商也有自己的通道,比如华为Push;除此之外应用有自己的独立通道,如微信。这种情况下就导致应用被频繁唤醒,整个系统其实是没有休眠的,没办法像iOS的通道这样控制行为。Wakelock长时间持锁上图是Android的休眠机制,刚开始的时候系统被频繁的唤醒,在息屏后一段时间会进入浅睡眠,这时网路访问就没有了、Syncs以及Jobs Deferred都不推荐使用,但是定期还是会有一个维护窗口,这段时间应用程序是可以被唤醒的。再持续一段时间后就进入了深度睡眠模式,这时不仅没有网络连接,GPS等也被禁止,这其实是理想的睡眠状态,实际是比较难进入这种状态的。为了不让系统的休眠导致应用进程结束,一般需要设置Wakelock。Wakelock有两种使用形式,一种是采用PowerMananger申请Wakelock锁,这段时间内系统不会进入休眠状态;另一种是直接使用底层的wake_lock或wake_unlock接口来避免系统进入休眠状态。Wakelock持锁如果忘记释放,会导致系统一直被频繁唤醒无法进入浅睡眠而一直处于异常耗电状态
  • 为什么GCC不使用部分寄存器?(Why doesn't GCC use partial registers?)
    问题 在使用gcc -s -nostdlib -nostartfiles -O3构建的linux上反汇编write(1,"hi",3)导致: ba03000000 mov edx, 3 ; thanks for the correction jester! bf01000000 mov edi, 1 31c0 xor eax, eax e9d8ffffff jmp loc.imp.write 我不从事编译器开发,但是由于移入这些寄存器的每个值都是恒定且已知的编译时,我很好奇为什么gcc不使用dl , dil和al 。 有人可能会争辩说,此功能不会对性能产生任何影响,但是当我们谈论数千个寄存器访问时mov $1, %rax => b801000000和mov $1, %al => b001之间的可执行文件大小有很大差异。一个程序。 如果软件优雅,它不仅体积小巧,而且对性能也有影响。 有人可以解释为什么“ GCC决定”这没关系吗? 回答1 部分寄存器在许多x86处理器上会导致性能下降,因为在写入时它们会从整个副本中重命名为不同的物理寄存器。 (有关寄存器重命名以实现乱序执行的更多信息,请参见此问答)。 但是,当一条指令读取整个寄存器时,CPU必须检测到单个物理寄存器中没有可用的正确体系结构寄存器值这一事实。 (这发生在问题/重命名阶段,因为CPU准备将uop发送到乱序调度程序中。)