簡體   English   中英

為什么在一次編譯指示出現關鍵操作后多次調用printf會產生亂碼的輸出?

[英]Why does multiple calls to printf following a pragma omp critical produce garbled output?

我有兩個程序會產生多個線程,並向stdout打印hello <TID> world <TID> 第一個在一個函數中打印它:

#include <omp.h>                                                
#include <stdio.h>                                               
int main() {                               
#pragma omp parallel                       
  {                                        
    int ID = omp_get_thread_num();         
#pragma omp critical                                  
    printf("hello  %d world %d\n", ID, ID);                                  
  }      
  return 0;                                  
}    

二分之二:

#include <omp.h>                                                  
#include <stdio.h>                                           
int main() {                               
#pragma omp parallel                       
  {                                        
    int ID = omp_get_thread_num();         
#pragma omp critical                       
    printf("hello  %d", ID);             
    printf("world %d\n", ID);                                                
  }  
  return 0;                                      
}      

使用該程序只需調用printf() ,輸出就不會出現亂碼。 但是,在第二個程序中,兩次調用printf() ,輸出都是亂碼。 在第二個程序中,永遠不會有亂碼干擾字符串序列。 從來沒有這樣的東西hhhhellloohello... 但是,不同的輸出字符串之間存在亂碼; 可能性的排列:

hello  27hello  62hello  52hello  50hello  10world 62...

舉個例子。

我以為#pragma omp critical會在pragma之后聲明互斥,直到並行化塊結束。 但這似乎並非如此。 #pragma omp critical是否僅適用於緊隨其后的語句?

為什么會發生這種情況的任何見解都是很好的。 伊扎克

#pragma omp parallel一樣, #pragma omp critical僅限於下一行,除非您也將其設為塊。

如果不想交錯輸出,請使用另一組花括號:

#pragma omp critical                       
{
    printf("hello  %d", ID);             
    printf("world %d\n", ID); 
}

可能是因為POSIX要求單個I / O函數調用是線程安全的,但不需要在單獨的函數調用之間進行鎖定。 規范的相關部分在以下頁面上是隱藏的:

規范的相關部分即將結束:

引用( FILE * )對象的所有函數(名稱以_unlocked結尾的函數除外)應表現為好像它們在內部使用flockfile()funlockfile()獲取這些( FILE * )對象的所有權一樣。

這意味着,例如, printf()必須在入口上執行flockfile(stdout) (等效funlockfile(stdout)在出口時執行funlockfile(stdout) (等效)。

這與您在OMP代碼中看到的完全匹配。 單個調用printf()的文本不會與任何其他並發調用交錯,但是printf()調用的順序在線程之間交錯。

這里 ,您可以看到應該一次由一個線程運行的代碼應該放置在代碼塊中。

添加名稱也是一個好主意,這樣,如果您使用多個這樣的指令,它們不會沖突,

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM