【发布时间】:2013-06-14 04:40:45
【问题描述】:
我有以下程序,我在 stackoverflow 上的其他人的帮助下编写了以了解缓存线和 CPU 缓存。我在下面发布了计算结果。
1 450.0 440.0
2 420.0 230.0
4 400.0 110.0
8 390.0 60.0
16 380.0 30.0
32 320.0 10.0
64 180.0 10.0
128 60.0 0.0
256 40.0 10.0
512 10.0 0.0
1024 10.0 0.0
我使用 gnuplot 绘制了一张图表,发布在下面。
我有以下问题。
我以毫秒为单位的计时计算是否正确? 440ms 似乎 有很多时间吗?
从图 cache_access_1(红线)我们可以得出结论, 缓存行的大小是 32 位(而不是 64 位?)
在代码中的 for 循环之间清除 缓存?如果是,我该如何以编程方式做到这一点?
如您所见,我在上面的结果中有一些
0.0值。? 这说明什么?也是测量的粒度 粗?
请回复。
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX_SIZE (512*1024*1024)
int main()
{
clock_t start, end;
double cpu_time;
int i = 0;
int k = 0;
int count = 0;
/*
* MAX_SIZE array is too big for stack.This is an unfortunate rough edge of the way the stack works.
* It lives in a fixed-size buffer, set by the program executable's configuration according to the
* operating system, but its actual size is seldom checked against the available space.
*/
/*int arr[MAX_SIZE];*/
int *arr = (int*)malloc(MAX_SIZE * sizeof(int));
/*cpu clock ticks count start*/
for(k = 0; k < 3; k++)
{
start = clock();
count = 0;
for (i = 0; i < MAX_SIZE; i++)
{
arr[i] += 3;
/*count++;*/
}
/*cpu clock ticks count stop*/
end = clock();
cpu_time = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("cpu time for loop 1 (k : %4d) %.1f ms.\n",k,(cpu_time*1000));
}
printf("\n");
for (k = 1 ; k <= 1024 ; k <<= 1)
{
/*cpu clock ticks count start*/
start = clock();
count = 0;
for (i = 0; i < MAX_SIZE; i += k)
{
/*count++;*/
arr[i] += 3;
}
/*cpu clock ticks count stop*/
end = clock();
cpu_time = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("cpu time for loop 2 (k : %4d) %.1f ms.\n",k,(cpu_time*1000));
}
printf("\n");
/* Third loop, performing the same operations as loop 2,
but only touching 16KB of memory
*/
for (k = 1 ; k <= 1024 ; k <<= 1)
{
/*cpu clock ticks count start*/
start = clock();
count = 0;
for (i = 0; i < MAX_SIZE; i += k)
{
count++;
arr[i & 0xfff] += 3;
}
/*cpu clock ticks count stop*/
end = clock();
cpu_time = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("cpu time for loop 3 (k : %4d) %.1f ms.\n",k,(cpu_time*1000));
}
return 0;
}
【问题讨论】:
-
我假设您使用的是clock(),因为您使用的是linux。我只知道osx和windows都有更好的高精度性能计数器。但是如果你跑得足够长,任何计时器最终都应该这样做:) 现在我注意到的一件事是你做了两步的力量。要测量你需要做随机模式。许多缓存是用非常简单的哈希实现的,它只占用低位。通过以两个步幅的精确功率访问数据来触发缓存别名实际上是某些 CPU 的性能缺陷。
-
我在那个问题上做了和你一样的事情:stackoverflow.com/questions/16249694/….
-
没关系,但不需要强制转换 malloc 结果。该行应为
int *arr = malloc(MAX_SIZE * sizeof *arr);。 -
@starmole: "windows ha[s] better high accuracy performance counters" - 在 可怕的。
-
Tony D: msdn.microsoft.com/en-us/library/windows/desktop/… QueryPerformance 计数器通常以时钟速率运行。 osx 也一样:developer.apple.com/library/mac/#qa/qa1398/_index.html。我确信linux有一个等价物,但我只是不知道那里的名字。是的,如果你在其他内核上有很多负载等,每个时间都会关闭。我只是读了一下时钟,这似乎是正确的选择。只是听到了奇怪的声音,对此感到抱歉。
标签: c performance optimization cpu cpu-architecture