Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 指针赋值或增量导致的性能增量(严格别名?)_Performance_Assembly_Visual C++_Intel_Cpu Cache - Fatal编程技术网

Performance 指针赋值或增量导致的性能增量(严格别名?)

Performance 指针赋值或增量导致的性能增量(严格别名?),performance,assembly,visual-c++,intel,cpu-cache,Performance,Assembly,Visual C++,Intel,Cpu Cache,更新:在Clang 7.0中演示问题的最小示例- 在256次迭代的基础上,我发现函数的性能从0μs变化到500-900μs(Visual Studio 2017): 为完整起见,以下是完整的组件输出: mov rax, QWORD PTR [rcx] lea rdx, QWORD PTR [rax+32776] mov QWORD PTR [rcx], rdx mov QWORD PTR [rax], rcx ret 0 性能差异的原因可能是什么?我

更新:在Clang 7.0中演示问题的最小示例-

在256次迭代的基础上,我发现函数的性能从0μs变化到500-900μs(Visual Studio 2017):

为完整起见,以下是完整的组件输出:

mov     rax, QWORD PTR [rcx]
lea     rdx, QWORD PTR [rax+32776]
mov     QWORD PTR [rcx], rdx
mov     QWORD PTR [rax], rcx
ret     0

性能差异的原因可能是什么?我现在的假设是,代码不能很好地处理CPU的缓存,但我无法理解为什么包含一条移动指令会导致这种情况?

如果您对其中任何一行进行注释,您要么重复存储到同一地址(可能在循环中进行了优化),要么根本没有存储。毫不奇怪,这段时间短得无法测量,精确到0微秒

在您链接的测试代码中,您在没有预热的情况下,在新分配的内存上,每个存储跨越32kiB。您可能在每次迭代中都会遇到一个软页面错误和一个副本。(malloced内存可能都被延迟映射到同一物理零页。)

256次迭代也完全不足以将CPU提升到正常/涡轮时钟速度,超出空闲速度

在我的i7-6700k Arch Linux destkop上(空闲800MHz,正常时钟速度3.9GHz,调控器/能量性能首选项=
balance\u性能
(不是默认的
balance\u功率
,因此速度更快):

我使用gcc8.2.1编译,并在循环中使用
while./a.out;do:;done
运行生成的可执行文件,这样CPU将保持高时钟速度。该程序打印的时间有点像
1.125us
+。对于页面错误+页面归零+更新页面表和刷新TLB来说,这听起来可能是正确的


使用Linux
perf stat
,我用计数的平均值运行了100次(“rate”secondary stats列中有一个伪单位,因为Arch还没有更新以修复这个伪单位。所以它实际上测量的是4.4GHz(我认为这是伪单位,我的CPU上禁用了Turbo以保持风扇安静)

peter@volta:/tmp$perf stat-etask clock,context switch,cpu迁移,页面错误,周期,分支,指令,uops\u发出。any,uops\u执行。线程,dtlb\u存储未命中。未命中导致未行走,tlb\u刷新。dtlb\u线程,dtlb\u加载未命中。未命中导致未行走-r100./a.out
“/a.out”(100次运行)的性能计数器统计信息:
1.15毫秒任务时钟#使用了0.889个CPU(+-0.33%)
0个上下文开关#40.000米/秒(+-49.24%)
0 cpu迁移#0.000 K/sec
191页错误#191250.000米/秒(+-0.09%)
4343915个周期#4343915.040 GHz(+-0.33%)(82.06%)
819685分支机构#819685480.000米/秒(+-0.05%)
4581597指令#1.05 insn/周期(+-0.05%)
6366610 uops#U发布任何#6366610010.000 M/s(+-0.05%)
6287015 uops_执行螺纹#6287015440.000 M/s(+-0.05%)
1271 dtlb_存储未命中。未命中导致步行1270910.000米/秒(+-0.21%)
tlb_齐平.dtlb_螺纹(0.00%)
dtlb_负载_未命中。未命中导致步行(0.00%)
0.00129289+-0.00000489秒经过时间(+-0.38%)
这些计数包括内核模式,但在256次循环迭代中,这是191次页面错误,因此该程序花费的绝大多数时间都在内核中。

一旦我们回到用户空间,超过1000个存储区会导致dTLB未命中,而第二级TLB也未命中,需要进行页面漫游。但没有加载


通过分配更多的内存,我们可能会得到更干净的数据,这样我们就可以增加
计数,而不会出现分段错误。使用
perf record
进行分析表明,程序总时间中只有大约20%花在
main
上;其余的是动态链接器/启动开销,部分来自打印。

我不确定C++标签适合这个问题。所显示的代码具有OP承认的不确定行为,并且输出组件被提供。从那时起,问题就变得严格地关于程序集,不管它是如何获得的。如果问题实际上是关于代码的,那么答案就是“因为UB”。“弗兰Sou-OISANDURIX问题是关于用C++编译器、Visual C++ 2017编译的代码,因此C++标签是完全可以接受的。没有任何问题必须在C++标准的范围内进行回答。”RSSSRICE,如果我确信它是偏离主题的话,我会自己删除它。看来我不是唯一一个有这种怀疑的人。我的观点是,如果你把C++的每一点都从根本上不会改变的问题中删除。编辑:第二,C++的专门知识对回答这个问题没有帮助。我不明白为什么这个问题应该引起C++社区的注意。@弗兰问题是C++代码的性能异常差。一个好的答案包括建议如何改变C++代码来修复或解决问题。(也就是说,如果它是可回答的,在它的当前状态下,它缺少很多上下文。甚至不清楚代码实际上是如何违反严格的别名规则或以其他方式调用未定义的行为的。)如果你能提供一个最小的、完整的、可验证的示例,包括外循环,这将是一个很好的选择
lea     rdx, QWORD PTR [rax+32776]
mov     QWORD PTR [rcx], rdx
mov     rax, QWORD PTR [rcx]
lea     rdx, QWORD PTR [rax+32776]
mov     QWORD PTR [rcx], rdx
mov     QWORD PTR [rax], rcx
ret     0
peter@volta:/tmp$ perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,dtlb_store_misses.miss_causes_a_walk,tlb_flush.dtlb_thread,dtlb_load_misses.miss_causes_a_walk -r100 ./a.out


 Performance counter stats for './a.out' (100 runs):

              1.15 msec task-clock                #    0.889 CPUs utilized            ( +-  0.33% )
                 0      context-switches          #   40.000 M/sec                    ( +- 49.24% )
                 0      cpu-migrations            #    0.000 K/sec                  
               191      page-faults               # 191250.000 M/sec                  ( +-  0.09% )
         4,343,915      cycles                    # 4343915.040 GHz                   ( +-  0.33% )  (82.06%)
           819,685      branches                  # 819685480.000 M/sec               ( +-  0.05% )
         4,581,597      instructions              #    1.05  insn per cycle           ( +-  0.05% )
         6,366,610      uops_issued.any           # 6366610010.000 M/sec              ( +-  0.05% )
         6,287,015      uops_executed.thread      # 6287015440.000 M/sec              ( +-  0.05% )
             1,271      dtlb_store_misses.miss_causes_a_walk # 1270910.000 M/sec                 ( +-  0.21% )
     <not counted>      tlb_flush.dtlb_thread                                         (0.00%)
     <not counted>      dtlb_load_misses.miss_causes_a_walk                                     (0.00%)

        0.00129289 +- 0.00000489 seconds time elapsed  ( +-  0.38% )