正确的QueryPerformanceCounter函数实现/时间每次都在变化

时间:2014-05-09 16:29:26

标签: c++ windows

我必须创建一个排序算法函数,它返回它用于完成排序的比较次数,份数和MICROSECONDS的数量。

我已经看到使用微秒我必须使用函数QueryPerformance计数器,因为它准确(Ps我知道它不能在OS之间移植)

所以我已经做到了:

void Exchange_sort(int vect[], int dim, int &countconf, int &countcopy, double &time)  
{

    LARGE_INTEGER a, b, oh, freq;

    QueryPerformanceFrequency(&freq); 
    QueryPerformanceCounter(&a);
    QueryPerformanceCounter(&b);
    oh.QuadPart = b.QuadPart - a.QuadPart; //Saves in oh the overhead time (?) accuracy
    QueryPerformanceCounter(&a); 

    int i=0,j=0; // The sorting algorithm starts

    for (i=0 ; i<dim-1 ; i++)
    {   for(j=i+1 ; j<dim; j++ )
        {
            countconf++; // +1 Comparisons
            if (vect[i]>vect[j])
            {
                scambio ( vect[i],vect[j] );  // It is a function that swaps 2 integers
                countcopy=countcopy+3;  // +3 copies
            }
        }
    }

    QueryPerformanceCounter(&b); // Ends timer
    time = (  ( (double)(b.QuadPart - a.QuadPart - oh.QuadPart)  /freq.QuadPart )            
    *1000000 ) ;

}

* 1000000实际上是给微秒......

我认为这样它应该可以工作,但每当我调用函数给它相同的数组维度时,它会返回不同的时间......我该如何解决?

非常感谢,抱歉我的编码错误

2 个答案:

答案 0 :(得分:1)

首先,性能计数器频率可能不那么好。它通常是几十万或更多,它提供微秒或几十微秒的分辨率,但你应该意识到它可能更糟。

其次,如果您的数组大小很小,您的排序可能会以纳秒或微秒结束,而您无法使用QueryPerformanceCounter准确测量。

第三,当您的基准测试过程正在运行时,Windows可能会使CPU远离它(相对)长时间,毫秒甚至数百毫秒。这将导致高度不规则和看似不稳定的时间。

我有两个建议,你可以互相追求:

  1. 我建议您使用RDTSC指令进行调查(使用内联汇编或编译器内在函数,甚至是现有的库。)这最有可能以更低的开销为您提供更好的分辨率。但我必须警告你,它有一些问题。

  2. 对于这种类型的基准测试,您必须使用完全相同的输入多次(数十或数百)运行排序例程,然后进行最小的时间测量。您应该采用这种策略的原因是,有一些现象会干扰您的时间并使其更长,但没有什么可以使您的排序比在纸上更快。因此,您需要多次运行测试,并希望您所有的神测量您测量的最快时间是实际运行时间,没有干扰或噪音。

  3. 更新:通过阅读有关问题的评论,您似乎正在尝试使用没有足够分辨率的计时器来计算一段非常短暂的代码。要么增加输入大小,要么使用RDTSC。

答案 1 :(得分:0)

您的问题的简短回答是,无法为同一功能的所有来电测量完全相同的时间。

您收到不同时间的事实预期,因为您的操作系统不是一个完美的实时系统,而是一个通用操作系统,同时运行多个进程并竞争由内核调度以获得自己的CPU周期。

另外,考虑到每次执行程序或函数时,其中一些指令可能位于RAM中,而某些指令可能在CPU L1或L2高速缓存中可用,并且可能会从一个执行到另一个。因此,在使用高精度精度评估函数调用的经过时间时,需要考虑许多变量。