2016-10-06 2 views
0

У меня очень мало опыта использования OpenMP. Я пытаюсь запустить цикл for параллельно, который вызывает другую внешнюю функцию. Я компилирую программу с MinGW, поэтому, к сожалению, у меня нет какой-либо ошибки, которая указывает, что я делаю неправильно, программа просто не запускается, когда я пытаюсь добавить параллель для внешнего цикла. findCombinations() - довольно большая функция, которая вызывает другую функцию. Мне интересно, можно ли использовать параллельный цикл в этом сценарии? и если да, то есть ли что-нибудь, что я делаю вопиюще неправильно?OpenMP - вызов внешних функций в параллельном для цикла

#pragma omp parallel for 
for(int j = 0; j < n[i].count; j++) { 
    int length = 0; 
    while(n[i].neighbourhoods[j][length].index != -1) length++; 
    bool used[length]; 
    memset(used, false, sizeof(used)); 
    findCombinations(&b, n[i].neighbourhoods[j], length, 0, 0, used, n[i].col); 
    free(n[i].neighbourhoods[j]); 
} 

Вот findCombinations()

int findCombinations(struct blocks *b, struct element neighbourhood[], int neighbourhoodSize, int start, int currLen, bool used[], int col) {  
    if (currLen == blocksize) { 
     b->blocks[b->count].elements = malloc((blocksize+1) * sizeof(struct element)); 
     b->blocks[b->count].col = col; 
     int blockCount = 0; 
     for (int i = 0; i < neighbourhoodSize; i++) { 
      if (used[i] == true) { 
       b->blocks[b->count].elements[blockCount++] = neighbourhood[i]; 
      } 
     } 
     b->blocks[b->count].elements[blocksize] = neighbourhood[neighbourhoodSize]; //ensures the last item is -1 
     b->blocks[b->count].signature = getSignature(b->blocks[b->count].elements); 
     return 1; 
    } 
    if (start == neighbourhoodSize) { 
     return 0; 
    } 
    int new = 0; 

    used[start] = true; 
    b->count += findCombinations(b, neighbourhood, neighbourhoodSize, start + 1, currLen + 1, used, col); 

    used[start] = false; 
    b->count += findCombinations(b, neighbourhood, neighbourhoodSize, start + 1, currLen, used, col); 

    return new; 
} 

Я думаю, что проблема может быть, что findCombinations() изменяет указатель я посылаю к нему, * б, что может вызвать состояние гонки. Моя проблема в том, что я не уверен, как обойти это.

+0

Просьба привести полный пример, чтобы мы могли лучше вам помочь. Сначала подумайте - убедитесь, что вы включили поддержку OpenMP в своем компиляторе. Например, если вы используете GCC для Linux, вам нужно включить '-fopenmp' в строку компиляции. – David

+0

Извините - добавлена ​​функция, вызываемая им сейчас. Я использую окна, и я установил MinGW для компиляции с gcc, просто компилируя через командную строку с -fopenmp –

+0

Конечно, у вас есть проблема со всеми вашими потоками, работающими над одним и тем же указателем 'b'. Это становится еще хуже, осознавая, что 'findCombinations()' является рекурсивной функцией. Вероятно, вы, вероятно, сможете это исправить, используя некоторые «критические» разделы здесь и там, но я сомневаюсь, что окончательная скорость будет стоить того. Если вам нужна производительность, вам, вероятно, лучше придется серьезно пересмотреть ваш алгоритм. – Gilles

ответ

0

Использование функций из других библиотек совершенно справедливо в параллельных регионах OpenMP при условии, что эти библиотеки предоставляют поточно-безопасные процедуры, в противном случае вы можете быть подвержены гонам данных, которые вы не можете контролировать, и, следовательно, вы можете сделать только один обычный вызов вовремя.

Если вы не уверены, что ваша программа является потокобезопасной, вы можете попробовать использовать некоторые инструменты, такие как helgrind или GCC/LLVM от Valgrind, thread sanitizer.