下面的示例在一个简单但不完全是微不足道的内存结构中调用了一些内存。然后它将显式设置为零或不设置,由EXPLICIT_RESET控制为1或0.然后将这些值相加。总和总是如预期的那样为零。
有趣的是时机。代码看起来比实际更长,因为#ifdefs可以在Cygwin上使用Microsoft的CL编译器v17.00和gcc 4.8.3进行计时。
cl /O2 /DEXPLICIT_RESET=0 test.c /Fetest.exe
./test.exe
我系统上的典型定时值为20000-25000。
cl /O2 /DEXPLICIT_RESET=1 test.c /Fetest.exe
./test.exe
典型时间值2500-3000。
gcc -O3 -DEXPLICIT_RESET=0 test.c -o test
./test.exe
典型定时值8000-10000。 (这些不具有可比性,因为我跳过了应该应用Win32代码的缩放因子。)
gcc -O3 -DEXPLICIT_RESET=1 test.c -o test
./test.exe
典型的定时值1000。
您可以进一步简化数据结构,但它们已经接近仍然会引发所述行为的限制。
我可以在没有显式初始化的情况下获得快速访问吗?
在我的真实程序中,显式重置内存需要很长时间,所以我想依赖calloc。但是我当然希望访问的内存很快。所以目前我陷入了困境:要么在calloc之上进行缓慢的初始化,要么缓慢访问。
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#include <time.h>
LARGE_INTEGER tu0, tu1;
#else
#include <sys/time.h>
struct timeval tu0, tu1;
#endif
struct dataType
{
int dummy1[4];
int dummy2;
};
struct blockType
{
int value;
struct dataType list[16];
};
struct pageType
{
struct blockType * list;
};
#define BLOCKS_PER_PAGE 100000
int main(int argc, char * argv[])
{
int timing, j, sum = 0;
struct pageType * pagep = (struct pageType *)
calloc(1, sizeof(struct pageType));
pagep->list = (struct blockType *)
calloc(BLOCKS_PER_PAGE, sizeof(struct blockType));
#if EXPLICIT_RESET
for (j = 0; j < BLOCKS_PER_PAGE; j++)
pagep->list[j].value = 0;
#endif
#ifdef _WIN32
QueryPerformanceCounter(&tu0);
#else
gettimeofday(&tu0, NULL);
#endif
for (j = 0; j < BLOCKS_PER_PAGE; j++)
sum += pagep->list[j].value;
#ifdef _WIN32
QueryPerformanceCounter(&tu1);
timing = tu1.QuadPart - tu0.QuadPart;
#else
gettimeofday(&tu1, NULL);
timing = 1000000 * (tu1.tv_sec - tu0.tv_sec )
+ (tu1.tv_usec - tu0.tv_usec);
#endif
printf("sum is %d, timing is %d\n", sum, timing);
exit(0);
}