Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.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++;如何在非常快的操作中进行台架标记_C++_Floating Point_Benchmarking_Chrono - Fatal编程技术网

C++ C++;如何在非常快的操作中进行台架标记

C++ C++;如何在非常快的操作中进行台架标记,c++,floating-point,benchmarking,chrono,C++,Floating Point,Benchmarking,Chrono,我在VC++2013,Windows 7-64,Intel i7 3.6 GHz。 我想测量非常快的数学运算的执行时间,例如,我想比较标准的fabsf()函数与其他“更快”方法的性能,或者标准的tanh()与Pade近似值的性能,等等 问题是,这些操作速度太快了,即使我运行了无数次,但在基准测试的结束和开始之间总是有0毫秒 我试图使用获得纳秒级的时间,但是它被舍入到十分之一毫秒,实际上不是一纳秒,所以在我的基准测试中,我仍然得到0纳秒级的时间 你能不能提供一段代码,我可以用它来运行我的基准测试

我在VC++2013,Windows 7-64,Intel i7 3.6 GHz。 我想测量非常快的数学运算的执行时间,例如,我想比较标准的
fabsf()
函数与其他“更快”方法的性能,或者标准的
tanh()
与Pade近似值的性能,等等

问题是,这些操作速度太快了,即使我运行了无数次,但在基准测试的结束和开始之间总是有0毫秒

我试图使用
获得纳秒级的时间,但是它被舍入到十分之一毫秒,实际上不是一纳秒,所以在我的基准测试中,我仍然得到0纳秒级的时间

你能不能提供一段代码,我可以用它来运行我的基准测试

这是我的:

#include <vector>
#include <chrono>
#include <ctime> 
using namespace std;

// 1/RAND_MAX
#define RAND_MAX_RECIP      0.00003051757f

int _tmain(int argc, _TCHAR* argv[])
{
    srand (static_cast <unsigned> (time(0)));

    // Fill a buffer with random float numbers
    vector<float> buffer;
    for (unsigned long i=0; i<10000000; ++i)
        buffer.push_back( (float)rand() * RAND_MAX_RECIP );

    // Get start time
    auto start = std::chrono::high_resolution_clock::now();

    for (unsigned long i=0; i<buffer.size(); ++i)
    {
        // do something with the float numbers in the buffer
    }

    // Get elapsed time
    auto finish = std::chrono::high_resolution_clock::now();

    printf("Executed in %d ns\n\n", std::chrono::duration_cast<std::chrono::nanoseconds>(finish-start).count());

    return 0;
}
#包括
#包括
#包括
使用名称空间std;
//1/RAND_最大值
#定义随机最大往复0.00003051757f
int _tmain(int argc,_TCHAR*argv[]
{
静态施法(时间(0));
//用随机浮点数填充缓冲区
向量缓冲区;
对于(无符号长i=0;i函数,如
fabs()
,它直接映射到指令,在合成基准测试中很难评估,因为它们的执行时间与管道延迟、内存访问时间等相比非常低。例如,如果有一个循环从数组中读取浮点值,找到其绝对值,然后将值写回数组,则执行第二,循环中的
fabs()
不会对执行时间产生影响——算法将受到内存限制,而不是CPU限制

同样,很难用一个数字来衡量像
fabs
这样的操作的“速度”。特别是对于某些多问题和无序处理器,执行此类操作所需的时间在很大程度上取决于之前和之后执行的其他操作


您应该看看Agner Fog关于x86/x64指令计时的页面,了解其中的细微差别。至于实用性,不要费心尝试对单个操作计时。尝试对您实际想要在其中使用该操作的算法计时。如果有差异,您知道使用哪一个,并且您知道该选择是可行的正确地为您的特定用例设置上下文。如果没有显著差异(我猜不会有)我认为最可能的问题是编译器注意到您没有使用计算结果,并优化了计算。您只需说服编译器不要这样做


我建议只保留所有计算结果的运行总和,并在打印循环所需时间后打印出来。您将忽略最终总和,但编译器不会知道这一点。

为了防止Jens提到的问题,您必须利用结果。为了解决无论我设置了多少次计数器,时间始终为0,您可以采用另一种方法。运行该操作1秒,并计算它被处理的次数

Psuedo代码是

   double TestFunc()
   {  
        double dSum=0, dForce=0;
        while(run)
        {
             // do test and keep the result
             // dForce += fabs(v); // whatever v is - just keep the result
             dSum +=1;  
        }
        printf("anchor answer is "+dForce) ;// this forces the compiler to generate code
        return dSum;
    }
然后运行该代码1秒,或者不管多长时间


然后,诀窍是在不使用测试代码的情况下运行相同的循环,并查看其迭代次数。然后从第二个数字中减去第一个数字,以查看代码(单独)所用的时间。

此类基准测试的一般策略是:

  • 估计你期望的时间(不知何故,可能是通过实验)
  • 编写代码多次执行测试序列,以便结果位于计时工具的合适范围内(比如1到100秒)
  • 根据您所测量的内容,选择一个优化级别
  • 检查生成的代码以确保它符合预期
  • 多次运行:一次填满所有缓存,然后至少重复两次以确保得到相同的答案
  • 仔细记录循环计数和次数
  • 通过2或3种不同的策略进行测试,确保在所有测试中得到一致的结果
  • 你会发现编译器在跳过没有任何用处的循环时会非常狡猾。禁用优化和/或使代码更加复杂,直到编译器生成你想要的序列


    仔细观察管道和缓存效果。除非或直到您能够通过多种策略在多次重复中获得完全匹配的答案,否则您不能依赖结果。这是实验性的计算机科学,而且很难。

    您可以使用
    rdtsc
    指令在时钟周期级别计时

    uint64_t begin = __rdtsc();
    _mm_lfence();
    // insert your code here
    _mm_lfence();
    uint64_t end = __rdtsc();
    uint64_t clocks = end - begin;
    
    围栏的存在是为了避免重新排列指令

    计时数十万次,取中值。以下陷阱适用:

  • 您可能正在使用带turbo boost的intel CPU。请禁用该功能。
    rdtsc
    始终根据处理器的基本时钟节拍。我通常使用throttlestop来实现此功能
  • <> LI>因为C++是编写的,一般来说,你无法控制编译器生成什么。没有任何东西避免编译器产生一个从内存中读取而不是寄存器登记的<代码> CMOV(条件移动)指令。
  • 指令序列的速度可以通过多种方式测量。例如,SSE乘法指令在结果可用之前需要5个时钟周期(“延迟”)。但是CPU可以在每个时钟周期发出1次乘法。还有其他指令可以在每个时钟周期发出多次。或者发出指令需要一个以上的时钟周期
  • 还存在需要可变时间的指令问题,例如
    DIV
    、分支或任何从内存读取的指令

  • 您可能希望在指令级运行基准测试。

    您是否可以确保您执行的操作