Dmi*_*try 1 c++ winapi average
我正在编写一个函数,以获取调用特定void (*)(void)aka void -> void函数特定次数的平均时钟。
我担心如果样本量太大,观测值的总和将会溢出并使平均值无效。
有没有一种标准的方法来消除此类问题中总和溢出的可能性?
注意:我知道这个示例太幼稚,无法得出有关性能的任何结论。我有兴趣消除总和溢出的可能性,而不是在性能方面做出任何结论。
注意2:我也理解,除非程序运行了数百年,否则64位无符号数字实际上不会溢出,但是我很好奇是否也可以消除这种假设。
这是我自包含的代码:
#include <Windows.h>
#include <stdio.h>
/**
* i want to parametrize the type which is used to store sample size
* to see whether it impacts performance
*/
template <typename sampleunit_t>
static inline ULONGLONG AveragePerformanceClocks (void (*f)(), sampleunit_t nSamples)
{
ULONGLONG sum;
sampleunit_t i;
sum = 0;
for (i = 0; i < nSamples; ++i) {
LARGE_INTEGER t1;
LARGE_INTEGER t2;
ULONGLONG dt;
QueryPerformanceCounter(&t1);
f();
QueryPerformanceCounter(&t2);
dt = t2.QuadPart - t1.QuadPart;
// sum may possibly overflow if program runs long enough with
// a large enough nSamples
sum += dt;
}
return (ULONGLONG)(sum / nSamples);
}
/* a cdecl callback that consumes time */
static void test1()
{
// don't optimize
volatile int i;
for (i = 0; i < 10000; ++i) {
}
}
int main(int argc, char **argv)
{
ULONGLONG avg;
avg = AveragePerformanceClocks<BYTE>(test1, 255);
printf("average clocks(truncated): %llu.\n", avg);
avg = AveragePerformanceClocks<WORD>(test1, 255);
printf("average clocks(truncated): %llu.\n", avg);
avg = AveragePerformanceClocks<DWORD>(test1, 255);
printf("average clocks(truncated): %llu.\n", avg);
avg = AveragePerformanceClocks<ULONGLONG>(test1, 255);
printf("average clocks(truncated): %llu.\n", avg);
system("pause");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
前n个元素的平均值为
SUM
Average = ---
n
Run Code Online (Sandbox Code Playgroud)
下一个元素Mi是
(SUM + Mi)
Average2 = ----------
n + 1
Run Code Online (Sandbox Code Playgroud)
因此,给定当前平均值,可以使用新读数找到下一个平均值。
(Average * n + Mi )
Average2 = -------------------
n + 1
Run Code Online (Sandbox Code Playgroud)
然后可以将其更改为不增加的方程式
n Mi
Average2 = Average * ----- + -----
n + 1 n + 1
Run Code Online (Sandbox Code Playgroud)
在实践中,时间的大小将适合计算机的数据类型。
如所指出的,这需要使用浮点表示,并且虽然不会由于溢出而失败,但是当n/(n+1)小于浮点分数部分的精度时仍然会失败。
有更好的重组。
Mi - Average
Average2 = Average + -------------
n + 1
Run Code Online (Sandbox Code Playgroud)
更好,因为它只有一个分区。