Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.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
C++ 装配性能调整_C++_Compiler Construction_Assembly_Compiler Theory - Fatal编程技术网

C++ 装配性能调整

C++ 装配性能调整,c++,compiler-construction,assembly,compiler-theory,C++,Compiler Construction,Assembly,Compiler Theory,我正在编写一个编译器(比其他任何东西都有趣),但我希望尽可能提高效率。例如,有人告诉我,在英特尔体系结构上,使用EAX以外的任何寄存器执行数学运算都会产生成本(大概是因为它会转换为EAX,以进行实际的数学运算)。这里至少有一个来源说明了这种可能性(http://www.swansontec.com/sregisters.html) 我想验证和衡量这些性能特征的差异。因此,我用C++编写了这个程序: #include "stdafx.h" #include <intrin.h> #in

我正在编写一个编译器(比其他任何东西都有趣),但我希望尽可能提高效率。例如,有人告诉我,在英特尔体系结构上,使用
EAX
以外的任何寄存器执行数学运算都会产生成本(大概是因为它会转换为
EAX
,以进行实际的数学运算)。这里至少有一个来源说明了这种可能性(http://www.swansontec.com/sregisters.html)

我想验证和衡量这些性能特征的差异。因此,我用C++编写了这个程序:

#include "stdafx.h"
#include <intrin.h>
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    __int64 startval;
    __int64 stopval;
    unsigned int value; // Keep the value to keep from it being optomized out

    startval = __rdtsc(); // Get the CPU Tick Counter using assembly RDTSC opcode

    // Simple Math: a = (a << 3) + 0x0054E9
    _asm {
        mov ebx, 0x1E532 // Seed
        shl ebx, 3
        add ebx, 0x0054E9
        mov value, ebx
    }

    stopval = __rdtsc();
    __int64 val = (stopval - startval);
    cout << "Result: " << value << " -> " << val << endl;

    int i;
    cin >> i;

    return 0;
}
#包括“stdafx.h”
#包括
#包括
使用名称空间std;
int _tmain(int argc,_TCHAR*argv[]
{
__int64 startval;
__int64-stopval;
unsigned int value;//保留要阻止其被优化的值
startval=uu rdtsc();//使用汇编rdtsc操作码获取CPU时钟计数器

//简单数学:a=(aZ80,可能还有TI,具有同步内存访问、无缓存和按顺序执行指令的优势。这使得计算每条指令的时钟数变得容易得多

在当前的x86 CPU上,使用AX或EAX的指令本身并不快,但某些指令可能比使用其他寄存器的指令短。这可能只会在指令缓存中保存一个字节!

去下载架构优化参考手册

有很多神话,我认为EAX的说法就是其中之一


还要注意的是,你不能再谈论“哪条指令更快”。在今天的硬件上,指令和执行时间之间没有1:1的关系。有些指令比其他指令更受欢迎,不是因为它们“更快”,而是因为它们打破了其他指令之间的依赖关系。

我相信如果有区别的话现在,这仅仅是因为一些传统指令对使用EAX的变体的编码较短。要测试这一点,请在比较循环计数之前重复测试用例一百万次或更多次。

启动程序所需的时间将比一次运行4条汇编指令所需的时间长得多,因此与汇编指令之间的任何差异都是存在的将淹没在噪音中。多次运行程序不会有帮助,但如果在循环中运行4条汇编指令(比如100万次),可能会有帮助。这样,程序只启动一次


仍然可能会有变化。我自己经历过的一件特别恼人的事情是,你的CPU可能具有类似Intel的功能,它会根据CPU的温度等因素动态调整速度。笔记本电脑更可能出现这种情况。如果你有这种情况,那么你将不得不在任何情况下关闭它enchmark结果是可靠的。

我认为这篇文章试图对EAX寄存器说的是,由于某些操作只能在EAX上执行,所以最好从一开始就使用它。这在8086上是非常正确的(想到MUL),但386使ISA变得更加正交,因此现在的情况就不那么正确了。

要想在RDTSC给出的级别上实现可重复的、确定的计时,您需要采取一些额外的步骤。首先,RDTSC不是串行化指令,因此它可以无序执行,这通常会使它在代码段l中变得毫无意义我喜欢上面的那个

您通常希望使用一条序列化指令,然后是您的RDTSC,然后是相关代码,另一条序列化指令和第二条RDTSC

在用户模式下,几乎唯一可用的串行化指令是CPUID。然而,这又增加了一个小问题:根据Intel的记录,CPUID需要不同的执行时间——前几次执行可能比其他几次慢

因此,代码的正常计时顺序如下所示:

XOR EAX, EAX
CPUID
XOR EAX, EAX
CPUID
XOR EAX, EAX
CPUID            ; Intel says by the third execution, the timing will be stable.
RDTSC            ; read the clock
push eax         ; save the start time
push edx

    mov ebx, 0x1E532 // Seed // execute test sequence
    shl ebx, 3
    add ebx, 0x0054E9
    mov value, ebx

XOR EAX, EAX      ; serialize
CPUID   
rdtsc             ; get end time
pop ecx           ; get start time back
pop ebp
sub eax, ebp      ; find end-start
sbb edx, ecx
我们开始接近了,但最后一点是在大多数编译器上使用内联代码是很难处理的:交叉缓存线也可能会产生一些影响,所以您通常希望强制代码与16字节对齐(段落)任何像样的汇编程序都会支持这一点,但编译器中的内联汇编通常不会


说到这里,我认为你在浪费时间。你可以猜到,我在这个级别上做了大量计时,我很确定你听到的完全是一个神话。事实上,所有最近的x86 CPU都使用一组所谓的“重命名寄存器”.长话短说,这意味着您用于寄存器的名称实际上无关紧要——CPU有一组更大的寄存器(例如,英特尔大约40个)它用于实际操作,因此在EBX和EAX中输入一个值对CPU内部真正要使用的寄存器几乎没有影响。两者都可以映射到任何重命名寄存器,这主要取决于指令序列启动时哪个重命名寄存器恰好是空闲的。

您得到的变量非常荒谬nce,因为
rdtsc
不会序列化执行。根据无法访问的执行状态详细信息,您尝试基准测试的指令实际上可能完全在
rdtsc
指令之间的间隔之前或之后执行!如果插入序列化指令,您可能会获得更好的结果(例如
cpuid
)紧跟在第一个
rdtsc
之后,紧跟在第二个
rdtsc之前。请参阅(PDF)了解详细信息。

我建议看一看,特别是汇编和微体系结构手册(2和3),以及测试代码,其中包括一个使用性能监视器计数器进行测量的相当复杂的框架。

我怀疑您的z80处理器是否有分支预测、预测执行、流水线执行,或者与缓存命中率相比有如此巨大的昂贵缓存未命中率(最后一个可能是我错了)