很明顯,沒有明確的方法或某些系統調用可幫助程序員將變量放入CPU高速緩存中。如何將我的結構變量放入CPU緩存以消除主內存頁面訪問時間?選項
但我認爲某種編程風格或精心設計的 算法可以增加將變量緩存到CPU高速緩存中的可能性。
這是我的例子:
我想在由相同類型的結構,在全局主存儲器 區域宣佈 數組的末尾附加8字節結構。
該過程持續重複進行400萬次操作。這個過程需要6秒鐘,每次操作1.5 us。我認爲這個結果表明這兩個內存區域沒有被緩存。
我從cache-oblivious algorithm得到了一些線索,所以我嘗試了幾個 的方法來加強這個。到現在爲止,沒有增強。
我覺得一些巧妙的代碼可以減少流逝的時間,最多可以減少10到100 次。請告訴我方式。
-------------------------------------------------------------------------
附加(2011-04-01)
達蒙〜感謝您發表評論!
看完您的評論後,我再次分析了我的代碼,發現我錯過了幾件事 。我附加的以下代碼是我的原始代碼的縮寫版本。
爲了準確測量每個操作的執行時間(在原始代碼中有幾種不同類型的操作),我使用clock_gettime()
函數插入了時間測量代碼。我想如果我測量每個操作的執行時間並累積它們,則可避免主循環的額外成本。
在原始代碼中,時間測量代碼被一個宏函數隱藏,所以我完全忘了它。
這段代碼的運行時間差不多是6秒。但是如果我在主循環中擺脫了時間測量功能,它會變成0.1秒。
由於clock_gettime()
函數支持非常高的精度(高達1納秒),在一個獨立的線程的基礎上執行,並且它需要非常大的結構,我認爲該函數導致緩存出主存儲器執行連續插入的區域。
再次感謝您的評論。爲了進一步增強,任何建議對我優化我的代碼都會非常有幫助。
我認爲分層定義的結構變量可能會導致不必要的時間成本,但首先我想知道它會變多少,然後再將其更改爲更多的C樣式代碼。
typedef struct t_ptr {
uint32 isleaf :1, isNextLeaf :1, ptr :30;
t_ptr(void) {
isleaf = false;
isNextLeaf = false;
ptr = NIL;
}
} PTR;
typedef struct t_key {
uint32 op :1, key :31;
t_key(void) {
op = OP_INS;
key = 0;
}
} KEY;
typedef struct t_key_pair {
KEY key;
PTR ptr;
t_key_pair() {
}
t_key_pair(KEY k, PTR p) {
key = k;
ptr = p;
}
} KeyPair;
typedef struct t_op {
KeyPair keyPair;
uint seq;
t_op() {
seq = 0;
}
} OP;
#define MAX_OP_LEN 4000000
typedef struct t_opq {
OP ops[MAX_OP_LEN];
int freeOffset;
int globalSeq;
bool queueOp(register KeyPair keyPair);
} OpQueue;
bool OpQueue::queueOp(register KeyPair keyPair) {
bool isFull = false;
if (freeOffset == (int) (MAX_OP_LEN - 1)) {
isFull = true;
}
ops[freeOffset].keyPair = keyPair;
ops[freeOffset].seq = globalSeq++;
freeOffset++;
}
OpQueue opQueue;
#include <sys/time.h>
int main() {
struct timespec startTime, endTime, totalTime;
for(int i = 0; i < 4000000; i++) {
clock_gettime(CLOCK_REALTIME, &startTime);
opQueue.queueOp(KeyPair());
clock_gettime(CLOCK_REALTIME, &endTime);
totalTime.tv_sec += (endTime.tv_sec - startTime.tv_sec);
totalTime.tv_nsec += (endTime.tv_nsec - startTime.tv_nsec);
}
printf("\n elapsed time: %ld", totalTime.tv_sec * 1000000LL + totalTime.tv_nsec/1000L);
}
8字節* 400萬大約是32 MB。如果這需要6秒,而你的CPU不是20歲,這不僅僅是緩存,還有其他的錯誤。一個合理的新CPU將使用非優化代碼依次寫出每秒數千兆字節。你是否可能每次重新分配內存? (此外,大多數情況下,緩存對於固定步長順序訪問非常有效,CPU可以自動並很好地執行此操作,而不是通過頁面邊界) – Damon 2011-03-31 13:58:41
您不會碰巧push_back到std :: vector或任何其他東西機會? - 雖然不會那麼長,但它幾何形狀的增長... –
Damon
2011-03-31 14:03:28
達蒙〜謝謝你的評論! 在閱讀您的評論之後,我再次分析了我的代碼,發現了我錯過的幾件事。我把錯過的東西和我的代碼的縮寫版本附加到上面。 – Nate 2011-04-01 04:58:52