在OpenMP 規范中,對屏障構造提出了以下限制:(參見第 259 頁,第 30-31 行):
除非已請求取消最內部的封閉并行區域,否則團隊中的所有執行緒都必須遇到每個屏障區域,否則根本不會遇到。
為了完整起見,OpenMP 規范對區域的定義如下(參見第 5 頁,第 9 行):
地區
在執行給定構造、結構化塊序列或 OpenMP 庫例程的特定實體期間遇到的所有代碼。區域包括被呼叫例程中的任何代碼以及任何實作代碼。[...]
我想出了一個非常簡單的例子,我在問自己它是否完全有效,因為障礙被放置在 if 條件中(并不是每個障礙都被每個執行緒“看到”)。盡管如此,每個執行緒的屏障數量是相同的,并且使用兩個編譯器的實驗表明代碼按預期作業。
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include "omp.h"
double zerotime;
double gettime(void) {
struct timeval t;
gettimeofday(&t, NULL);
return t.tv_sec t.tv_usec * 1e-6;
}
void print(const char *format, ...) {
va_list args;
va_start (args, format);
#pragma omp critical
{
fprintf(stdout, "Time = %1.1lfs ", gettime() - zerotime);
vfprintf (stdout, format, args);
}
va_end (args);
}
void barrier_test_1(void) {
for (int i = 0; i < 5; i ) {
if (omp_get_thread_num() % 2 == 0) {
print("Path A: Thread %d waiting\n", omp_get_thread_num());
#pragma omp barrier
} else {
print("Path B: Thread %d waiting\n", omp_get_thread_num());
sleep(1);
#pragma omp barrier
}
}
}
int main() {
zerotime = gettime();
#pragma omp parallel
{
barrier_test_1();
}
return 0;
}
對于四個執行緒,我得到以下輸出:
Time = 0.0s Path B: Thread 1 waiting
Time = 0.0s Path B: Thread 3 waiting
Time = 0.0s Path A: Thread 0 waiting
Time = 0.0s Path A: Thread 2 waiting
Time = 1.0s Path B: Thread 1 waiting
Time = 1.0s Path B: Thread 3 waiting
Time = 1.0s Path A: Thread 2 waiting
Time = 1.0s Path A: Thread 0 waiting
Time = 2.0s Path B: Thread 1 waiting
Time = 2.0s Path B: Thread 3 waiting
Time = 2.0s Path A: Thread 0 waiting
Time = 2.0s Path A: Thread 2 waiting
...
這表明所有執行緒都很好地等待慢速路徑 B操作并配對,即使它們沒有放在同一個分支中。但是,我仍然對規范感到困惑,我的代碼是否完全有效。將此與例如CUDA進行對比,其中給出了有關相關__syncthreads()例程的以下宣告:
__syncthreads() is allowed in conditional code but only if the conditional evaluates identically across the entire thread block, otherwise the code execution is likely to hang or produce unintended side effects.
Thus, in CUDA, such code as written above in terms of __syncthreads() would be invalid, because the condition omp_get_thread_num() % 2 == 0 evaluates differently depending on the thread.
uj5u.com熱心網友回復:
在 OpenMP 規范中,對屏障構造提出了以下限制:(參見第 259 頁,第 30-31 行):
除非已請求取消最內部的封閉并行區域,否則團隊中的所有執行緒都必須遇到每個屏障區域,否則根本不會遇到。
這個描述有點問題,因為它barrier是一個獨立的指令。這意味著除了指令本身之外,它沒有關聯的代碼,因此沒有“屏障區域”這樣的東西。
盡管如此,我認為意圖是明確的,無論是從措辭本身還是從屏障實作的傳統行為來看:如果沒有任何取消,如果執行包含給定barrier構造的最內部并行區域的團隊中的任何執行緒到達該屏障,那么所有執行緒在團隊必須達到相同的barrier構造。不同的屏障結構代表不同的屏障,每個屏障都要求所有執行緒在任何行程通過之前到達。
但是,我仍然對規范感到困惑,我的代碼是否完全有效。
我看到您的測驗代碼的行為表明這兩個障礙被視為一個障礙。但是,這與解釋規范無關,因為您的代碼確實不滿足您詢問的要求。在這種情況下,規范不要求程式以任何特定方式失敗,但它當然也不需要您觀察到的行為。您很可能會發現,使用不同版本的編譯器或不同的 OpenMP 實作,程式的行為會有所不同。編譯器有權假定您的 OpenMP 代碼符合 OpenMP 規范。
當然,在您的特定示例的情況下,解決方案是barrier將不同條件分支中的兩個構造替換為緊跟在else塊之后的單個構造。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/331905.html
上一篇:C中的memchr如何實際作業?
