C++ 是否有一种编程方法来估计CPU执行fp操作所需的时间?

C++ 是否有一种编程方法来估计CPU执行fp操作所需的时间?,c++,c,linux,cpu,instructions,C++,C,Linux,Cpu,Instructions,我所说的“浮点运算”是指“浮点运算”。我正在开发一个Linux机器。是否有一个系统调用以静态度量的形式返回此值,或者您是否可以使用C/C++/其他语言的算法来测试此值 编辑:我应该提到,这不是为了测试代码的效率。在一次采访中,我被问到一个理论算法需要多长时间才能运行。我必须计算出将执行多少次失败,然后乘以每次操作所需的时间,得出一个粗略的估计。我只是觉得这是一个有趣的问题。这几乎肯定不是一个有用的指标。许多其他因素都会影响代码效率——特别是缓存命中/未命中 话虽如此,本主题中有一个链接到您可以使

我所说的“浮点运算”是指“浮点运算”。我正在开发一个Linux机器。是否有一个系统调用以静态度量的形式返回此值,或者您是否可以使用C/C++/其他语言的算法来测试此值


编辑:我应该提到,这不是为了测试代码的效率。在一次采访中,我被问到一个理论算法需要多长时间才能运行。我必须计算出将执行多少次失败,然后乘以每次操作所需的时间,得出一个粗略的估计。我只是觉得这是一个有趣的问题。

这几乎肯定不是一个有用的指标。许多其他因素都会影响代码效率——特别是缓存命中/未命中


话虽如此,本主题中有一个链接到您可以使用的,但您应该知道,您可能看不到系统的最大触发器与应用程序性能之间的任何关联

试图确定触发器“在真空中”所花费的时间没有多大意义,因为还有很多其他因素影响它(操作数是否在内存/缓存/寄存器中,它实际上是什么类型的操作,如果编译器发出x87/SSE/SSE2/…指令,它是否涉及“奇怪的”IEEE754值,如果处理器管道得到有效使用,如果代码对分支预测器友好,…)


相反,您应该在算法的实际代码上使用探查器,以查看真正的瓶颈是什么,以及在特定代码中实际花费了多少时间。

有一种快速的脏方法,即在执行某些操作之前和之后获取时间戳,并减去它们以查看消耗了多少时间。然而,这并不十分准确。

您想要使用的是Agner Fog的软件。这就是他用来测量指令的延迟和吞吐量,以产生他著名的结果。它有很好的文档记录,包括可以在自己的代码中使用的设备驱动程序(以及如何安装它们的说明)。这一点特别有用,因为为了测量某些量,例如实际CPU频率,您需要访问用户级代码通常无法访问的数据

编辑:根据您对面试问题的编辑,估计浮点密集型操作的运行时间,您可以使用以下公式:

time = efficiency * number_of_floating_point_operations / peak_flops.
从这个链接可以找到许多处理器每个内核的峰值触发器

这些数量中的每一个都可能难以计算/估计,但效率是最困难的,因为它可能取决于许多因素,例如:

  • 算法是计算还是内存受限
  • 算法在多大程度上可以使用SIMD(例如SSE/AVX/FMA)
  • 算法在多大程度上可以使用MIMD(例如多核)
  • 您的实现在多大程度上使用了不同的缓存级别
  • 为了使这一点更清楚,我们考虑两种算法:矩阵乘法和点积。计算这两种算法的浮点运算数很容易。矩阵乘法的浮点运算数为
    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写一个,或者,如果你很好的话,自己写一个……特别是什么浮动操作?如果你对精确映射的东西感兴趣