在尝试为我的代码(使用128位整数)的一些选项进行基准测试时,我观察到一个我根本无法理解的行为.有人可以点亮这个吗?
#include <stdio.h>
#include <stdint.h>
#include <time.h>

int main(int a,char** b)
{
    printf("Running tests\n");

    clock_t start = clock();
    unsigned __int128 t = 13;
    for(unsigned long i = 0; i < (1UL<<30); i++)
        t += 23442*t + 25;
    if(t == 0) printf("0\n");
    printf("u128,+25,took %fs\n",double(clock() - start)/CLOCKS_PER_SEC);

    start = clock();
    t = 13;
    for(unsigned long i = 0; i < (1UL<<30); i++)
        t += 23442*t;
    if(t == 0) printf("0\n");
    printf("u128,no+,double(clock() - start)/CLOCKS_PER_SEC);

    start = clock();
    unsigned long u = 13;
    for(unsigned long i = 0; i < (1UL<<30); i++)
        u += 23442*u + 25;
    if(u == 0) printf("0\n");
    printf("u64,double(clock() - start)/CLOCKS_PER_SEC);

    start = clock();
    u = 13;
    for(unsigned long i = 0; i < (1UL<<30); i++)
        u += 23442*u;
    if(u == 0) printf("0\n");
    printf("u64,double(clock() - start)/CLOCKS_PER_SEC);

    return 0;
}

(请注意,printf在这里,以便gcc不优化for循环)
在我的系统上,这可靠地产生以下输出:

u128,took 2.411922s
u128,took 1.799805s
u64,took 1.797960s
u64,took 2.454104s

虽然128位整数行为是有意义的,但我看不清如何使用较少操作的64位循环显着(30%)较慢.

这是一个已知的行为吗?在编写这种循环时尝试从优化中获益的一般规则是什么?

编辑:仅当使用-O3选项编译时才会观察到该行为.

gcc -lstdc++ -O3 -o a main.cpp

u128,took 2.413949s
u128,took 1.799469s
u64,took 1.798278s
u64,took 2.453414s

gcc -lstdc++ -O2 -o a main.cpp

u128,took 2.415244s
u128,took 1.800499s
u64,took 1.798699s
u64,took 1.348133s

解决方法

循环非常紧张,依赖停顿,ALU忙等来发挥主导作用.因此,结果不是可靠的,对其他因素比实际的指令执行更敏感.

注意,25可以与乘法一起并行计算.

PS.我的结果在4970K:

gcc version 5.2.1 20151010
gcc -lstdc++ -O2 -o a a.cpp

u128,took 1.346360s
u128,took 1.022965s
u64,took 1.020189s
u64,took 0.765725s

编辑:在对-O2和-O3进行反汇编后,主要区别在于代码生成. (以上原因仍然在不同的测试机器/环境下保持-O2产生略微不同的结果)

-02:

400618:       48 69 d2 93 5b 00 00    imul   $0x5b93,%rdx,%rdx
40061f:       48 83 e8 01             sub    $0x1,%rax
400623:       75 f3                   jne    400618 <_Z4testv+0x18>

-O3:

400628:       66 0f 6f d9             movdqa %xmm1,%xmm3
40062c:       83 c0 01                add    $0x1,%eax
40062f:       66 0f 6f c1             movdqa %xmm1,%xmm0
400633:       66 0f f4 cc             pmuludq %xmm4,%xmm1
400637:       3d 00 00 00 20          cmp    $0x20000000,%eax
40063c:       66 0f f4 da             pmuludq %xmm2,%xmm3
400640:       66 0f 73 d0 20          psrlq  $0x20,%xmm0
....

O3生成矢量化代码,而循环具有很大的依赖性,不能从矢量化中获得值.它实际上生成了更复杂的代码,因此具有更长的时间.

c – GCC优化:如何减少操作速度?的更多相关文章

  1. 使用最新的Flurry SDK和ios4重新启动应用程序

    我真的希望这对我来说只是一个愚蠢的错误.我很高兴使用Flurry但这样的事情会导致我的应用被拒绝.解决方法我写了关于这个的Flurry,他们很快回到我身边,他们会调查这个.大约一个星期后,他们回信并表示他们已经在v2.6中修复了它,现在可用了.我似乎无法重现这个问题.不是说我很棒或者什么,但我还是单枪匹马地解决了这个问题.

  2. 将POD规范属性与其Xcode配置中的不同构建设置相关联(例如,发布,调试)

    我正在尝试为现有的库项目创建POD规范.在Xcode项目中,构建设置为不同的构建配置定义了不同的预处理器宏例如:对于“调试”配置:对于“发布”配置:如何将这些设置映射到相应的POD规范?

  3. 在ios上使用来自框架的boost :: filesysystem路径

    我一直在使用Boost作为PeteGoodliffe脚本构建的框架已有一段时间了.效果很好.最近我遇到了一个问题,可以通过将以下代码放入另一个全新的XCode项目中的视图控制器的viewDidLoad中来重现:当路径对象被销毁时会导致EXC_BAD_ACCESS.有没有其他人遇到这个问题?

  4. 如何在Xcode 4.1中调试OpenCL内核?

    我有一些OpenCL内核没有做他们应该做的事情,我很想在Xcode中调试它们.这可能吗?当我在我的内核中使用printf()时,OpenCL编译器总是给我一大堆错误.解决方法将格式字符串转换为constchar*似乎可以解决此问题.这适用于Lion:这有上述错误:

  5. ios – LLVM,GCC 4.2和Apple LLVM编译器之间的区别3.1

    LLVMGCC4.2和AppleLLVM编译器3.1之间的主要区别是什么?

  6. ios – 在/usr/lib/system/libcache.dylib中,缺少必需的架构armv6

    在试图为iphoneos编写一个虚拟程序时,Xcode4,gcc似乎没有超出初始的sysroot目录如果我把sysroot,以下作品,但感觉非常干酪,而且不可伸缩.这里发生了什么?

  7. 如何在Xcode 4.5中关闭垃圾回收,并在切换ARC时摆脱cl ang错误1?

    我刚刚重新打开了一个被设置为使用垃圾收集的项目,并且我最后在Xcode3中打开.现在在Xcode4.5中再次打开它,并希望将其现代化,我正在尝试切换ARC.但是,当构建时,会导致clangerrorerrorerrorerrorininin::::::::::::clang:error:不能同时指定’-fobjc-arc’和’-fobjc-gc-only’啊,我需要关闭我之前使用的垃圾收集.但是,

  8. 六种语言实现输出乘法口诀表

    六种语言实现输出乘法口诀表Objective-cC语言javaJavaScriptSwiftPython可以看出不同语言又不同的写法,从上到下,代码越来越少,越来越简洁,也能够看出这些语言的各自的一些特点。

  9. Swift---一门智能型的编程语言

    Swift是苹果公司于2014年推出的一门全新的编程语言,目前已进化至第三版。简单地说,Swift是一门智能型的语言,为程序员解决了在使用很多其他的编程语言的过程中所经常遇到的问题。下面,我就拿Swift和C语言进行对比,用几个例子为大家展示Swift为何是“智能”的。从变量类型的自动推断中也可以看出,Swift具备一定的“智能”。那么,Swift是否受到了大家的欢迎呢?考虑到Swift也才推出来两年,这个排行算是不错的了。

  10. android – 使用FFmpeg检索专辑封面

    我正在开发一个依赖于FFmpeg来检索音频元数据的Android应用程序.我知道可以使用FFMpeg以编程方式检索专辑封面.但是,一旦您解码了艺术,如何生成图像文件以便在应用程序中使用?

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部