C++ 是否有一种编程方法来估计CPU执行fp操作所需的时间?
我所说的“浮点运算”是指“浮点运算”。我正在开发一个Linux机器。是否有一个系统调用以静态度量的形式返回此值,或者您是否可以使用C/C++/其他语言的算法来测试此值C++ 是否有一种编程方法来估计CPU执行fp操作所需的时间?,c++,c,linux,cpu,instructions,C++,C,Linux,Cpu,Instructions,我所说的“浮点运算”是指“浮点运算”。我正在开发一个Linux机器。是否有一个系统调用以静态度量的形式返回此值,或者您是否可以使用C/C++/其他语言的算法来测试此值 编辑:我应该提到,这不是为了测试代码的效率。在一次采访中,我被问到一个理论算法需要多长时间才能运行。我必须计算出将执行多少次失败,然后乘以每次操作所需的时间,得出一个粗略的估计。我只是觉得这是一个有趣的问题。这几乎肯定不是一个有用的指标。许多其他因素都会影响代码效率——特别是缓存命中/未命中 话虽如此,本主题中有一个链接到您可以使
编辑:我应该提到,这不是为了测试代码的效率。在一次采访中,我被问到一个理论算法需要多长时间才能运行。我必须计算出将执行多少次失败,然后乘以每次操作所需的时间,得出一个粗略的估计。我只是觉得这是一个有趣的问题。这几乎肯定不是一个有用的指标。许多其他因素都会影响代码效率——特别是缓存命中/未命中
话虽如此,本主题中有一个链接到您可以使用的,但您应该知道,您可能看不到系统的最大触发器与应用程序性能之间的任何关联 试图确定触发器“在真空中”所花费的时间没有多大意义,因为还有很多其他因素影响它(操作数是否在内存/缓存/寄存器中,它实际上是什么类型的操作,如果编译器发出x87/SSE/SSE2/…指令,它是否涉及“奇怪的”IEEE754值,如果处理器管道得到有效使用,如果代码对分支预测器友好,…)
相反,您应该在算法的实际代码上使用探查器,以查看真正的瓶颈是什么,以及在特定代码中实际花费了多少时间。有一种快速的脏方法,即在执行某些操作之前和之后获取时间戳,并减去它们以查看消耗了多少时间。然而,这并不十分准确。您想要使用的是Agner Fog的软件。这就是他用来测量指令的延迟和吞吐量,以产生他著名的结果。它有很好的文档记录,包括可以在自己的代码中使用的设备驱动程序(以及如何安装它们的说明)。这一点特别有用,因为为了测量某些量,例如实际CPU频率,您需要访问用户级代码通常无法访问的数据 编辑:根据您对面试问题的编辑,估计浮点密集型操作的运行时间,您可以使用以下公式:
time = efficiency * number_of_floating_point_operations / peak_flops.
从这个链接可以找到许多处理器每个内核的峰值触发器
这些数量中的每一个都可能难以计算/估计,但效率是最困难的,因为它可能取决于许多因素,例如:
2*n*n*n
。对于点积,它是2*n
矩阵乘法如果做得好,它的计算范围可以充分受益于SIMD和MIMD。
对于小氮,其效率将从低开始,而对于大氮,其效率将稳定。我自己的实现可以达到75%。英特尔MKL的性能超过95%(但使用FMA的性能不到90%)
因此,对大n的矩阵乘法时间的包络线后估计是假设100%的效率,给出时间=2*n^3/峰值\u次
然而,对于点积,对于小n,效率将从高开始,而对于大n,效率将下降到平台。那是因为它的内存有限。因此,对于大n,效率取决于读取内存的速度。由于具有四个内核的现代桌面的峰值浮点数将超过100 glop,浮点数为4或8字节,因此我估计大型n
的效率接近1%,给出时间=0.01*n/peak\u浮点数
。我继续测试了它(参见下面的代码)。我在我的系统上得到了大约2.2个GLOPS,峰值为236 GFLOPS,这大约是峰值的1%。我的系统的带宽约为11 GB/s
大多数算法都是内存受限的,因此了解系统读取内存(DDR3、DDR4等)的速度是估计时间最有用的指标之一
所以一般来说,如果你知道一个算法的浮点运算的数量和处理器的峰值触发器,你首先要问的是,对于大n,这个算法是计算范围还是内存范围,那么对于时间的后包络估计,我假设计算范围和内存范围的效率是100%我想估算一下效率
此代码根据点积估计数据速率和GFLOPS
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
float dot(float *x, float *y, int n) {
float sum = 0;
for(int i=0; i<n; i++) {
sum += x[i]*y[i];
}
return sum;
}
int main(){
const int LEN = 1 << 28;
float *x = new float[LEN];
float *y = new float[LEN];
for(int i=0; i<LEN; i++) { x[i] = 1.0*rand()/RAND_MAX - 0.5; y[i] = 1.0*rand()/RAND_MAX - 0.5;}
uint32_t size = 2*sizeof(float)*LEN;
clock_t time0 = clock();
float sum = dot(x,y,LEN);
clock_t time1 = clock();
double dtime = (double)(time1 - time0) / CLOCKS_PER_SEC;
double rate = 1.0*size/dtime*1E-9;
double flops = 2.0*LEN/dtime*1E-9;
printf("sum %f, dtime %f, rate %f, flops %f\n", sum, dtime, rate,flops);
}
#包括
#包括
#包括
#包括
#包括
浮点点(浮点*x,浮点*y,整数n){
浮点数和=0;
对于(int i=0;i以下内容提供了我的一个基准测试的可变性思想,该基准测试使用相同汇编代码指令的长序列,尝试填充管道,不同的测试使用可变数量的寄存器。然后这只是为了添加
Intel(R) Core(TM) i7-4820K CPU running at near 3.9 GHz
Speeds adding to 1 Register 2 Registers 3 Registers 4 Registers
32 bit Integer MIPS 4303 8553 11997 12294
32 bit Float MFLOPS 1304 2608 3866 3866 SP
64 bit Float MFLOPS 1304 2608 3866 3865 DP
32 bit MMX Int MIPS 7824 14902 14936 14902
32 bit SSE MFLOPS 5215 10431 15464 15463 SP
64 bit SSE2 MFLOPS 2608 5216 7732 7731 DP
32 bit SSE2 Int MIPS 15647 29803 29872 29803
64 bit SSE2 Int MIPS 7823 14902 14936 14902
做手术所需的“时间”本身并不是一个非常有用的指标。当然,一个女人生孩子需要9个月,但一个城市有很多女人,并非所有的女人都能或愿意按要求生孩子。其他人怎么说(作为回答或评论),再加上linux内核仍然缺少一个pre-cog功能。你可以缠着Linus写一个,或者,如果你很好的话,自己写一个……特别是什么浮动操作?如果你对精确映射的东西感兴趣