我使用llvm-mca来计算一堆代码的总周期,认为它们会预测它的运行时间.但是,动态测量运行时几乎没有相关性.那么:为什么由llvm-mca计算的总周期不能准确预测运行时?我可以用llvm-mca以更好的方式预测运行时吗?
细节:
我想知道,对于不同类型的下面的代码的运行时间begin(和end)迭代器,对startValue正在0.0或0ULL:
std::accumulate(begin, end, starValue)
Run Code Online (Sandbox Code Playgroud)
为了预测运行时,我使用Compiler Explorer(https://godbolt.org/z/5HDzSF)及其LLVM机器码分析器(llvm-mca)插件,因为llvm-mca是"一个使用可用信息的性能分析工具"在LLVM(例如调度模型)中静态测量性能".我使用了以下代码:
using vec_t = std::vector<double>;
vec_t generateRandomVector(vec_t::size_type size)
{
std::random_device rnd_device;
std::mt19937 mersenne_engine {rnd_device()};
std::uniform_real_distribution dist{0.0,1.1};
auto gen = [&dist, &mersenne_engine](){
return dist(mersenne_engine);
};
vec_t result(size);
std::generate(result.begin(), result.end(), gen);
return result;
}
double start()
{
vec_t vec = generateRandomVector(30000000);
vec_t::iterator vectorBegin = vec.begin();
vec_t::iterator vectorEnd = vec.end();
__asm volatile("# LLVM-MCA-BEGIN stopwatchedAccumulate");
double result = std::accumulate(vectorBegin, vectorEnd, 0.0);
__asm …Run Code Online (Sandbox Code Playgroud) 我在llvm clang Apple LLVM 8.0.0版(clang-800.0.42.1)上反汇编代码:
int main() {
float a=0.151234;
float b=0.2;
float c=a+b;
printf("%f", c);
}
Run Code Online (Sandbox Code Playgroud)
我编译时没有-O规范,但我也试过-O0(给出相同)和-O2(实际上计算值并存储它预先计算)
产生的反汇编如下(我删除了不相关的部分)
-> 0x100000f30 <+0>: pushq %rbp
0x100000f31 <+1>: movq %rsp, %rbp
0x100000f34 <+4>: subq $0x10, %rsp
0x100000f38 <+8>: leaq 0x6d(%rip), %rdi
0x100000f3f <+15>: movss 0x5d(%rip), %xmm0
0x100000f47 <+23>: movss 0x59(%rip), %xmm1
0x100000f4f <+31>: movss %xmm1, -0x4(%rbp)
0x100000f54 <+36>: movss %xmm0, -0x8(%rbp)
0x100000f59 <+41>: movss -0x4(%rbp), %xmm0
0x100000f5e <+46>: addss -0x8(%rbp), %xmm0
0x100000f63 <+51>: movss %xmm0, -0xc(%rbp)
...
Run Code Online (Sandbox Code Playgroud)
显然它正在做以下事情:
我正在寻找一种公式/方法来衡量一条指令的速度,或者更具体地说是通过CPU周期给出每条指令的"得分".
我们以下面的汇编程序为例,
nop
mov eax,dword ptr [rbp+34h]
inc eax
mov dword ptr [rbp+34h],eax
Run Code Online (Sandbox Code Playgroud)
以及英特尔Skylake的以下信息:
mov r,m:吞吐量= 0.5延迟= 2
mov m,r:吞吐量= 1延迟= 2
nop:吞吐量= 0.25延迟=非
inc:吞吐量= 0.25延迟= 1
我知道程序中指令的顺序在这里很重要,但我希望创建一些通用的东西,不需要"对单循环准确"
任何人都知道我该怎么做?
非常感谢
assembly ×3
c ×2
performance ×2
x86 ×2
x86-64 ×2
c++ ×1
instructions ×1
llvm-codegen ×1
llvm-mca ×1
opcode ×1