通过使用OpenMP,我试图并行化这样定义的字典的创建。
typedef struct Symbol {
int usage;
char character;
} Symbol;
typedef struct SymbolDictionary {
int charsNr;
Symbol *symbols;
} SymbolDictionary;
我做了下面的代码。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <omp.h>
static const int n = 10;
int main(int argc, char* argv[]) {
int thread_count = strtol(argv[1], NULL, 10);
omp_set_dynamic(0);
omp_set_num_threads(thread_count);
SymbolDictionary **symbolsDict = calloc(omp_get_max_threads(), sizeof(SymbolDictionary*));
SymbolDictionary *dict = NULL;
int count = 0;
#pragma omp parallel for firstprivate(dict, count) shared(symbolsDict)
for (int i = 0; i < n; i++) {
if (count == 0) {
dict = calloc(1, sizeof(SymbolDictionary));
dict->charsNr = 0;
dict->symbols = calloc(n, sizeof(Symbol));
#pragma omp critical
symbolsDict[omp_get_thread_num()] = dict;
}
dict->symbols[count].usage = i;
dict->symbols[count].character = 'a' + i;
++dict->charsNr;
++count;
}
if (omp_get_max_threads() > 1) {
// merge the dictionaries
}
for (int j = 0; j < symbolsDict[0]->charsNr; j++)
printf("symbolsDict[0][%d].character: %c\nsymbolsDict[0][%d].usage: %d\n",
j,
symbolsDict[0]->symbols[j].character,
j,
symbolsDict[0]->symbols[j].usage);
for (int i = 0; i < omp_get_max_threads(); i++)
free(symbolsDict[i]->symbols);
free(symbolsDict);
return 0;
}
代码编译并运行,但我不确定omp块是如何工作的,我是否正确地实现了它,特别是我必须在循环开始时将dict
与symbolsDict
附加在一起,因为我不知道线程何时完成它的工作。通过这样做,可能不同的线程将同时写入symbolsDict
内部,但是写入到不同的存储器中。虽然线程将使用不同的访问点,但是dict对于每个线程应该是不同的,我不确定这是个好办法。
我用不同的线程测试了代码,创建了不同大小的字典。我没有遇到任何问题,但也许这只是偶然。
基本上我在文档中寻找理论部分。所以我想知道我是否正确地实现了代码?如果没有,什么是不正确的,为什么?
1条答案
按热度按时间jgwigjjp1#
不同的线程会同时在不同的内存中写入symbolsDict。虽然线程会使用不同的访问点,但是每个线程的dict应该是不同的,我不确定这是不是一个好的方法。
这不是一个好方法,但它是安全的。一个更干净的方法是这样的:
请注意,内部杂注是
omp for
,而不是omp parallel for
,因此它使用外部parallel
块来分配其工作。nowait
是一种性能改进,它避免了循环末尾的线程障碍,因为它是并行部分的最后一部分,并且线程无论如何都会在该部分末尾等待所有其他线程。