首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有一种编程方法来估计CPU执行fp操作所需的时间?

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

Stack Overflow用户
提问于 2014-07-30 23:50:25
回答 5查看 278关注 0票数 0

所谓"fp运算“是指”浮点运算“。我在做一个Linux机器。是否有一个系统调用将此值作为静态度量返回,或者您可以用C/C++/其他语言的算法来测试这个值?

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-07-31 07:55:12

您想要使用的是Agner的软件“测量时钟周期和性能监测的测试程序”。这是他用来测量指令延迟和吞吐量的方法,以生成他著名的指令表。它有详细的文档,包括设备驱动程序(以及如何安装它们的说明),您可以在自己的代码中使用这些驱动程序。这特别有用,因为为了测量某些数量,例如实际的CPU频率,您需要访问用户级代码通常无法访问的模型专用寄存器(MSR)。

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

代码语言:javascript
复制
time = efficiency * number_of_floating_point_operations / peak_flops.

许多处理器的每个核心的峰值触发器可以从这个链接flops-per-cycle-for-sandy-bridge-and-haswell-sse2-avx-avx2中找到。

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

  1. 算法是计算的还是内存的?
  2. 该算法如何使用SIMD (例如SSE/AVX/FMA)?
  3. 该算法能很好地使用MIMD (例如多核)?
  4. 您的实现如何使用不同的缓存级别?

为了更清楚地说明这一点,让我们考虑两个算法:矩阵乘法和点积。对于这两种算法来说,浮点运算的次数很容易计算。矩阵乘法的浮点运算数为2*n*n*n。对于点积,它是2*n。

矩阵乘法,如果做的正确,它是计算界,可以充分受益于SIMD和MIMD。对于小n,它的效率很低,对于大n,它的效率很低,我自己的实现达到75%。英特尔MKL获得超过95% (但不到90%使用FMA)。

因此,对于大n的矩阵乘法时间的后包络估计是假定100%的效率,给出了time = 2*n^3/peak_flops**.**。

然而,对于点乘积,对于小n,效率会很高,而对于大n,效率会下降到一个平台,这是因为它是内存绑定的。因此,对于大的n,效率取决于存储器的读取速度。对于一台大约10 GB/s的现代机器。由于一个有四个核心的现代桌面将有一个峰值触发器,超过100个GLOPS,浮点数为4或8个字节,所以我估计大型time = 0.01*n/peak_flops.的效率接近1%。我进行了测试(请参阅下面的代码)。在我的系统上,我得到了大约2.2个GLOPS,峰值为236 GFLOPS,这大约是峰值的1%。我的系统带宽约为11 GB/s。

大多数算法都是内存绑定的,因此知道系统读取内存的速度(DDR3,DDR4,.)是估计时间的最有用的指标之一。

所以一般来说,如果你知道一个算法的浮点运算的数量和处理器的峰值触发器,你首先要问的是,如果算法是计算界还是内存界是大n,那么对于一个信封后估计时间,我假设效率是100%,对于计算界和内存界,我将查找带宽来估计效率。

此代码估计来自点积的数据速率和GFLOPS。

代码语言:javascript
复制
    #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);
    }
票数 3
EN

Stack Overflow用户

发布于 2014-07-30 23:56:24

这几乎肯定不是一个有用的指标。很多,很多其他的事情都会影响代码的效率--尤其是高速缓存的命中/错过。

尽管如此,有一个关于这个主题的ServerFault螺纹链接到您可以使用的英特尔基准套件,但是您应该知道,您可能不会看到系统的最大失败与应用程序的性能之间有任何关联。

票数 4
EN

Stack Overflow用户

发布于 2014-07-31 00:00:06

尝试确定“真空中”触发器所花费的时间是没有什么意义的,因为影响它的因素还有很多(操作数是否在内存/缓存/寄存器中,它实际上是什么类型的操作,如果编译器发出X87/SSE/SSE 2/.说明是否涉及“奇怪”的IEEE754值,如果有效地使用处理器管道,如果代码是分支预测器友好的,.)。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25048828

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档