[英]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函數調用是線程安全的,但不需要在單獨的函數調用之間進行鎖定。 規范的相關部分在以下頁面上是隱藏的:
flockfile()
funlockfile()
ftrylockfile()
規范的相關部分即將結束:
引用(
FILE *
)對象的所有函數(名稱以_unlocked
結尾的函數除外)應表現為好像它們在內部使用flockfile()
和funlockfile()
獲取這些(FILE *
)對象的所有權一樣。
這意味着,例如, printf()
必須在入口上執行flockfile(stdout)
(等效funlockfile(stdout)
在出口時執行funlockfile(stdout)
(等效)。
這與您在OMP代碼中看到的完全匹配。 單個調用printf()
的文本不會與任何其他並發調用交錯,但是printf()
調用的順序在線程之間交錯。
從這里 ,您可以看到應該一次由一個線程運行的代碼應該放置在代碼塊中。
添加名稱也是一個好主意,這樣,如果您使用多個這樣的指令,它們不會沖突,
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.