原文:http://blog.csdn.net/sy8111/archive/2006/09/05/1178107.aspx
下面用一個簡單的小程式來驗證False Sharing對效能的影響。
這個小程式同時運行兩個線程,對同一塊記憶體地區的臨近位置進行int大小的多次讀寫。線程1讀寫第1個int值,線程2讀寫第2個int值。按照預想,如果兩個int相隔太近,落入同一個cache line,兩個線程就會因為"偽共用"而花費額外的時間進行緩衝一致性通訊和維護,造成效能下降。
TestFalseSharing.cpp 是主程式,Thread.h/cpp 是對Win32 Thread API的簡單封裝,Timer.h/cpp是對CRT time函數的簡單封裝。
// TestFalseSharing.cpp</p><p>#include "stdafx.h"<br />#include "Thread.h"<br />#include "Timer.h"</p><p>#define COUNT 3000000000<br />#define DISTANCE 4</p><p>DWORD WINAPI t1_p(void* a)<br />{<br />int* arr = (int*)a;<br />for (int i=0; i<COUNT; i++)<br />arr[0] = 30;</p><p>return 0;<br />}</p><p>DWORD WINAPI t2_p(void* a)<br />{<br />int* arr = (int*)a;<br />for (int i=0; i<COUNT; i++)<br />arr[DISTANCE] = 30;</p><p>return 0;<br />}</p><p>int arr[64];</p><p>int main(int argc, char* argv[])<br />{<br />yshi::Timer timer(std::cout);</p><p>// Start threads<br />yshi::WinThread t1(t1_p, arr);<br />yshi::WinThread t2(t2_p, arr);</p><p>// Wait for all threads to terminate<br />t1.Wait();<br />t2.Wait();</p><p>timer.Stop();</p><p>return 0;<br />}
// Thread.h</p><p>namespace yshi<br />{</p><p>typedef LPTHREAD_START_ROUTINE WinThreadProc; // int func_name(void*)</p><p>// This class is exported from the Win32.dll<br />class WIN32_API WinThread<br />{<br />public:<br />WinThread(WinThreadProc aProc, void* aParam, bool aSuspend = false);<br />void Resume();<br />void Wait();<br />virtual ~WinThread();<br />private:<br />HANDLE _handle;<br />private:<br />WinThread(const WinThread&);<br />WinThread& operator=(const WinThread&);<br />};</p><p>}
// Thread.cpp</p><p>#include "stdafx.h"<br />#include "Thread.h"</p><p>namespace yshi<br />{</p><p>WinThread::WinThread(WinThreadProc aProc, void* aParam, bool aSuspend)<br />{<br />HANDLE h = CreateThread(NULL, 0, aProc, aParam, aSuspend ? 0x04 : 0x00, NULL);<br />if (h == NULL)<br />{<br />throw GetLastError();<br />}</p><p>_handle = h;<br />}</p><p>void WinThread::Resume()<br />{<br />DWORD ret = ResumeThread(_handle);<br />if (ret == -1)<br />{<br />throw GetLastError();<br />}<br />}</p><p>void WinThread::Wait()<br />{<br />DWORD ret = WaitForSingleObject(_handle, INFINITE);<br />if (ret == WAIT_FAILED)<br />throw GetLastError();<br />}</p><p>WinThread::~WinThread()<br />{<br />if (_handle != 0)<br />CloseHandle(_handle);<br />}</p><p>}
// Timer.h</p><p>namespace yshi<br />{</p><p>class DEBUGUTIL_API Timer<br />{<br />public:<br />Timer(std::ostream& aOutput);<br />~Timer();<br />void Start();<br />void Stop();<br />private:<br />void Print(std::ostream& aOutput);<br />private:<br />std::ostream& mOutput;<br />unsigned long long mTimeDiff;<br />private:<br />Timer& operator=(const Timer&);<br />};</p><p>}
// Timer.cpp</p><p>#include "Timer.h"</p><p>#include <ctime></p><p>namespace yshi<br />{</p><p>Timer::Timer(std::ostream& aOutput) : mOutput(aOutput)<br />{<br />Start();<br />}</p><p>Timer::~Timer()<br />{<br />}</p><p>void Timer::Start()<br />{<br />mTimeDiff = time(0);<br />}</p><p>void Timer::Stop()<br />{<br />mTimeDiff = time(0) - mTimeDiff;<br />Print(mOutput);<br />}</p><p>void Timer::Print(std::ostream& aOutput)<br />{<br />aOutput << "Time spent: " << mTimeDiff << " seconds/n";<br />}</p><p>}
運行結果
資料距離(DISTANCE) 花費時間(秒)
4 21
8 21
16 10
32 10
可以看到,當距離達到16個int,也就是64位元組的時候,"偽共用"消失,而64位元組也就是我的機器的cache line 大小。