全國建筑業(yè)四庫一平臺seo賺錢暴利
cacheline是內(nèi)存調(diào)度的基本結(jié)構(gòu),其大小一般為32B或者64B。關(guān)于本機具體的配置信息可以在配置文件中看到:
這里可以看到我的這臺機器的cacheline大小是64B。對于cacheline在多核處理器中有一個偽共享的狀態(tài),具體可以參考以下博客:高速緩存?zhèn)喂蚕?- 知乎(這個大佬寫了1K多篇文章,我感覺需要好好消化消化。)
所謂“偽共享”實際上是主存中的一個cacheline中的內(nèi)容,在同一時刻只能被多核中的一個捕獲處理。
程序如下:
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <string.h>
#include <thread>
#include <chrono>
#include <iostream>
#include <atomic>struct common
{volatile unsigned long a;volatile unsigned long b;
};
struct common_fulfill
{volatile unsigned long a;unsigned long az[7];volatile unsigned long b;unsigned long bz[7];
};using namespace std;
int main(int argc, char** argv)
{cout << "no-fulfill" << endl;do{common c;c.a = 0;c.b=0;volatile bool brun = true;thread t1([&c,&brun](){while(brun)c.a+=1;});thread t2([&c,&brun](){while(brun)c.b+=1;});std::this_thread::sleep_for(std::chrono::seconds(1));brun=false;//std::atomic_thread_fence(std::memory_order_seq_cst);t1.join();t2.join();cout << "a:" << c.a << "\t b:" << c.b << endl;}while(0);cout << "fulfill" << endl;do{common_fulfill c;c.a = 0;c.b=0;volatile bool brun = true;thread t1([&c,&brun](){while(brun)c.a+=1;});thread t2([&c,&brun](){while(brun)c.b+=1;});std::this_thread::sleep_for(std::chrono::seconds(1));brun=false;//std::atomic_thread_fence(std::memory_order_seq_cst);t1.join();t2.join();cout << "a:" << c.a << "\t b:" << c.b << endl;}while(0);cout << "add-per-second" << endl;do{common_fulfill c;c.a = 0;c.b=0;volatile bool brun = true;thread t1([&c,&brun](){while(brun)c.a+=1;});std::this_thread::sleep_for(std::chrono::seconds(1));brun=false;//std::atomic_thread_fence(std::memory_order_seq_cst);t1.join();cout << "a:" << c.a << endl;}while(0);return 0;
}
注意,我在struct c中的a和b都增加了volatile關(guān)鍵字,這個關(guān)鍵字的作用在于將緩存和主存硬綁定,有點同步打開文件描述符的意思。這樣,可以預期到內(nèi)存會被以cacheline為單位上鎖。然后進行編譯。
這里用的是O2進行優(yōu)化,然后執(zhí)行,結(jié)果如下:
這個地方可以發(fā)現(xiàn),在沒有填充的情況下,1秒內(nèi)訪問的速度是3.5*10^8;而將struct c填充到128字節(jié)的訪問次數(shù)是4.9*10^8。幾乎同樣的代碼,將最后的單CPU每秒能進行加法數(shù)量的統(tǒng)計去掉之后,結(jié)果如下:
可以看到,兩次的情況,不填充的速度總是要遠遠遜色于填充的情況。我們在做服務(wù)器程序深度優(yōu)化的時候,要注意這個硬件細節(jié),有時候能夠極大地加快程序的運行速度??梢宰⒁獾?#xff0c;偽共享狀態(tài)只是影響了CPU的運行時間,服務(wù)器的大量CPU時間會在等待鎖中消耗,所以現(xiàn)在無鎖代碼非常流行。另外為什么增加或者修改代碼的大小就會影響CPU的執(zhí)行效率呢?這個問題還是沒有得到答案。