[英]Parallelizing recursion in a for-loop using readdir
我想並行化一個 C 程序,該程序使用 OpenMP 和 C 遞歸計算目錄及其子目錄的大小。
我的問題是,當我使用opendir
進入目錄並使用readdir
遍歷子目錄時,我只能一個接一個地訪問它們,直到到達最后一個子目錄。 這一切都按順序運作良好。
然而,當並行化程序時,我認為將子目錄的數量分成兩半(甚至更小的分區)並使用 OpenMp 任務通過子目錄遞歸是有意義的。
顯然,由於 for 循環的結構,我不能簡單地將問題大小(= 子目錄的數量)分成兩半,並且這樣的循環不能使用#pragma omp for
並行化。
有人知道如何將此 function 拆分為任務嗎? 任何幫助將不勝感激。
這是我的一些代碼(我已經刪除了我認為與這個問題無關的部分。)
int calculate_folder_size(const char *path) {
struct stat sb;
if (S_ISREG(sb.st_mode)) { // if it's a file, not a directory (base case)
return sb.st_size;
}
DIR *folder = opendir(path);
struct dirent *element;
size_t size = 4096;
for (element = readdir(folder); element != NULL; element = readdir(folder)) {
//(...)
if (element->d_type == DT_DIR) {
// recursive call of calculate_folder_size
size += calculate_folder_size(name);
} else {
//(...)
}
}
}
closedir(folder);
return size;
}
您需要一個支持 OpenMP 任務的現代編譯器,它從等式中刪除了 Visual C++。 如果您使用的是這樣的編譯器,您需要做的就是將對calculate_folder_size()
的遞歸調用轉換為 OpenMP 任務:
int calculate_folder_size(const char *path) {
struct stat sb;
if (S_ISREG(sb.st_mode)) { // if it's a file, not a directory (base case)
return sb.st_size;
}
DIR *folder = opendir(path);
struct dirent *element;
size_t size = 4096;
for (element = readdir(folder); element != NULL; element = readdir(folder)) {
//(...)
if (element->d_type == DT_DIR) {
// Make sure the task receives a copy of the path
char *priv_name = strdup(name); // (1)
// recursive call of calculate_folder_size
// (2)
#pragma omp task shared(size) firstprivate(priv_name)
{
// (3)
#pragma omp atomic update
size += calculate_folder_size(priv_name);
free(priv_name); // (4)
}
} else {
//(...)
}
}
// (5)
#pragma omp taskwait
closedir(folder);
return size;
}
這里的重要部分是:
您需要向任務傳遞一個名稱參數,該參數將一直存在並保留其值,直到任務被執行,這可能是將來的任何時間。 因此,您需要復制name
,例如,使用strdup(3)
。
任務應該記住priv_name
的當前值,因為它將在循環的下一次迭代中改變。 因此,首先對firstprivate
進行priv_name
處理。 它還需要能夠在父上下文中修改size
,因此為它shared
。
由於所有任務都在更新父 scope 中的相同size
變量,因此需要使用atomic update
來保護訪問。
不再需要私有名稱,必須對其進行處置。
在返回size
之前,父任務應該等待所有子任務首先完成。
必須從並行區域內調用此 function 才能並行完成其工作:
int size;
#pragma omp parallel
#pragma omp single
size = calculate_folder_size("/some/path");
限制事物仍然並行運行的並行深度可能是一個好主意。 我把它留給你弄清楚如何:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.