我想通過使用預取來加速單個程序。我的程序的目的只是爲了測試。這裏是做什麼的:使用預取加速隨機內存訪問
- 它同樣採用了尺寸
- 的兩個int緩衝區它讀取一個接一個的第一緩衝器的所有值
- 它的索引讀取值在第二緩衝
- 它總結從第一緩衝
- 它所有越做越大
- 前面的步驟最後,我打印自願和非自願CP的數量所採取的所有數值U
在第一次,第一次緩衝區中的值包含其索引的值(參見圖1)。功能createIndexBuffer
在下面的代碼中)。
這將是我的程序的代碼更加清晰:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#define BUFFER_SIZE ((unsigned long) 4096 * 100000)
unsigned int randomUint()
{
int value = rand() % UINT_MAX;
return value;
}
unsigned int * createValueBuffer()
{
unsigned int * valueBuffer = (unsigned int *) malloc(BUFFER_SIZE * sizeof(unsigned int));
for (unsigned long i = 0 ; i < BUFFER_SIZE ; i++)
{
valueBuffer[i] = randomUint();
}
return (valueBuffer);
}
unsigned int * createIndexBuffer()
{
unsigned int * indexBuffer = (unsigned int *) malloc(BUFFER_SIZE * sizeof(unsigned int));
for (unsigned long i = 0 ; i < BUFFER_SIZE ; i++)
{
indexBuffer[i] = i;
}
return (indexBuffer);
}
unsigned long long computeSum(unsigned int * indexBuffer, unsigned int * valueBuffer)
{
unsigned long long sum = 0;
for (unsigned int i = 0 ; i < BUFFER_SIZE ; i++)
{
unsigned int index = indexBuffer[i];
sum += valueBuffer[index];
}
return (sum);
}
unsigned int computeTimeInMicroSeconds()
{
unsigned int * valueBuffer = createValueBuffer();
unsigned int * indexBuffer = createIndexBuffer();
struct timeval startTime, endTime;
gettimeofday(&startTime, NULL);
unsigned long long sum = computeSum(indexBuffer, valueBuffer);
gettimeofday(&endTime, NULL);
printf("Sum = %llu\n", sum);
free(indexBuffer);
free(valueBuffer);
return ((endTime.tv_sec - startTime.tv_sec) * 1000 * 1000) + (endTime.tv_usec - startTime.tv_usec);
}
int main()
{
printf("sizeof buffers = %ldMb\n", BUFFER_SIZE * sizeof(unsigned int)/(1024 * 1024));
unsigned int timeInMicroSeconds = computeTimeInMicroSeconds();
printf("Time: %u micro-seconds = %.3f seconds\n", timeInMicroSeconds, (double) timeInMicroSeconds/(1000 * 1000));
}
如果我啓動它,我得到以下的輸出:
$ gcc TestPrefetch.c -O3 -o TestPrefetch && ./TestPrefetch
sizeof buffers = 1562Mb
Sum = 439813150288855829
Time: 201172 micro-seconds = 0.201 seconds
快速,快捷!根據我的知識(我可能是錯的),有這樣一個快速程序的原因之一是,當我順序訪問我的兩個緩衝區時,可以在CPU緩存中預取數據。
我們可以使它更復雜,以便數據(幾乎)在CPU緩存中處於優先地位。例如,我們可以只改變createIndexBuffer
功能:
unsigned int * createIndexBuffer()
{
unsigned int * indexBuffer = (unsigned int *) malloc(BUFFER_SIZE * sizeof(unsigned int));
for (unsigned long i = 0 ; i < BUFFER_SIZE ; i++)
{
indexBuffer[i] = rand() % BUFFER_SIZE;
}
return (indexBuffer);
}
讓我們再次嘗試程序:慢
$ gcc TestPrefetch.c -O3 -o TestPrefetch && ./TestPrefetch
sizeof buffers = 1562Mb
Sum = 439835307963131237
Time: 3730387 micro-seconds = 3.730 seconds
18倍以上!
我們現在到達我的問題。鑑於新createIndexBuffer
功能,我想使用prefetch加快computeSum
功能
unsigned long long computeSum(unsigned int * indexBuffer, unsigned int * valueBuffer)
{
unsigned long long sum = 0;
for (unsigned int i = 0 ; i < BUFFER_SIZE ; i++)
{
__builtin_prefetch((char *) &indexBuffer[i + 1], 0, 0);
unsigned int index = indexBuffer[i];
sum += valueBuffer[index];
}
return (sum);
}
當然我也不得不改變我createIndexBuffer
爲了它分配有一個多元素
我重新啓動一個緩衝我的程序:不是更好!由於預取可能會慢於一個「for」循環迭代,我可以過,但兩個元素之前
__builtin_prefetch((char *) &indexBuffer[i + 2], 0, 0);
不是更好不預取一個元素!兩個循環迭代? 不是更好?三? **我嘗試了它直到50(!!!),但我無法提高我的功能computeSum
的性能。
可我想幫助理解爲什麼 非常感謝您的幫助
我對你的'罪'建議的回答高於你的答案,而不是低於(我確實犯了一個錯誤...) –