Sunday, November 21, 2021

[C++] const volatile restrict

compiler 的最佳化編譯,為了增快程式速度,

有時候會很聰明的將程式碼編譯成和原 code 不同,但意思相同的 object code

如下:

for (int i = 0; i < 10000; i++) {

    a = 5;

   a =  a * i;

}

compiler 可以簡化成下列一條敘述:

a = 5 * 9999;

編譯器最佳化,就讓程式變得更有效率。

 

但是當我們某些程式片段不希望做最佳化的時候呢? 就要使用 volatile 關鍵字

volatile 是 C 的關鍵字,用來修飾資料型態,是告訴 compiler 不要對這一個變數的程式碼區段做最佳化。

volatile 表明某個變量的值可能在外部被改變,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器裡的備份

它可以適用於基礎類 型如:int,char,long......也適用於C的結構和C++的類。當對結構或者類對象使用volatile修飾的時候,結構或者類的所有成員 都會被視為volatile.

volatile 使用時機

該關鍵字在多線程環境下經常使用,因為在編寫多線程的程序時,同一個變量可能被多個線程修改,而程序通過該變量同步各個線程。

簡單示例:


復制代碼代碼如下:

DWORD __stdcall threadFunc(LPVOID signal)

{

int* intSignal=reinterdivt_cast(signal);

*intSignal=2;

while(*intSignal!=1)

sleep(1000);

return 0;

}


該線程啟動時將intSignal 置為2,然後循環等待直到intSignal 為1 時退出。顯然intSignal的值必須在外部被改變,否則該線程不會退出。但是實際運行的時候該線程卻不會退出,即使在外部將它的值改為1,看一下對應的偽匯編代碼就明白了:

 


mov ax,signal

label:

if(ax!=1)

goto label


對於C編譯器來說,它並不知道這個值會被其他線程修改。自然就把它cache在寄存器裡面。C 編譯器是沒有線程概念的,這時候就需要用到volatile。volatile 的本意是指:這個值可能會在當前線程外部被改變。也就是說,我們要在threadFunc中的intSignal前面加上volatile關鍵字,這時 候,編譯器知道該變量的值會在外部改變,因此每次訪問該變量時會重新讀取,所作的循環變為如下面偽碼所示:

label:

mov ax,signal

if(ax!=1)

goto label


注意:一個參數既可以是const同時是volatile,是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。

restrict 

restrict 是 C 的關鍵字,只能用來修飾 pointer,目的是協助 compiler 做最佳化

是告知 compiler ,這一個 restrict pointer 是唯一指向 data 的 pointer,

意即程式當中不會透過其他變數 ( pointer,或者直接存取 ) 來 access 此 data,

例子如下:

int * restrict rptr = (int*) malloc(10*sizeof(int));

int a[10];

int * ptr;

ptr = a;

for(int i =0; i<10;i++) { 

    ptr += 5;

    rptr +=5;

    a *= 5;

    ptr += 3;

    rptr += 3;

}

當 compiler 看到 rptr 為 restric,就會用 rptr += 8 取代 rptr += 3 和 rptr += 5

而 ptr 就不應該被直接替換,因為它不是唯一會 access 該 data 的變數

 

C99 用到restrict的例子:

void* memcpy (void* restrict destination, const void* restrict source, size_t n);

代表destination和source區段是不可重疊的

 

FILE *fopen(const char *restrict pathname, const char *restrict type);


https://www.itread01.com/content/1550372781.html

https://liquid0118.pixnet.net/blog/post/48494846

No comments:

Post a Comment

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能