Использование цикла OpenMP in for приводит к некорректному выводу [duplicate]

Angular1

Для людей, которые используют AngularJS , может справиться с этой ситуацией, используя Promises.

Здесь it говорит,

Обещания могут использоваться для отключения асинхронных функций и позволяют объединять несколько функций вместе.

Вы можете найти приятное объяснение здесь .

Пример, найденный в docs , упомянутом ниже.

  promiseB = promiseA.then(
    function onSuccess(result) {
      return result + 1;
    }
    ,function onError(err) {
      //Handle error
    }
  );

 // promiseB will be resolved immediately after promiseA is resolved 
 // and its value will be the result of promiseA incremented by 1.

Angular2 and Later

In Angular2, посмотрите на следующий пример, но его рекомендовал использовать Observables с Angular2.

 search(term: string) {
     return this.http
  .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
  .map((response) => response.json())
  .toPromise();

}

Вы можете использовать это таким образом,

search() {
    this.searchService.search(this.searchField.value)
      .then((result) => {
    this.result = result.artists.items;
  })
  .catch((error) => console.error(error));
}

См. здесь оригинал . Но TypScript не поддерживает native es6 Promises , если вы хотите его использовать, для этого вам может понадобиться плагин.

Кроме того, здесь представлены обещания spec определите здесь.

5
задан wolfPack88 18 November 2014 в 19:01
поделиться

2 ответа

В вашем коде в настоящее время состояние гонки , поэтому результат неверен. Чтобы проиллюстрировать, почему это так, воспользуемся простым примером:

Вы работаете в 2 потоках, а массив - int input[4] = {1, 2, 3, 4};. Вы правильно инициализируете sum до 0 и готовы к запуску цикла. На первой итерации вашего цикла поток 0 и поток 1 читают sum из памяти как 0, а затем добавьте их соответствующий элемент в sum и запишите его обратно в память. Однако это означает, что поток 0 пытается записать sum = 1 в память (первый элемент - 1 и sum = 0 + 1 = 1), а поток 1 пытается записать sum = 2 в память (второй элемент - 2 и sum = 0 + 2 = 2). Конечный результат этого кода зависит от того, какой из последних заканчивается последним, и поэтому записывает в память последним, что является условием гонки. Не только это, но и в этом конкретном случае ни один из ответов, которые мог бы произвести код, правильный! Есть несколько способов обойти это; Ниже я расскажу о трех основных:

#pragma omp critical:

В OpenMP существует так называемая директива critical. Это ограничивает код так, что только один поток может что-то делать за раз. Например, ваш for -loop может быть записан:

#pragma omp parallel for schedule(static)
for(i = 0; i < snum; i++) {
    int *tmpsum = input + i;
#pragma omp critical
    sum += *tmpsum;
}

Это устраняет условие гонки, когда только один поток обращается и записывается в sum за раз. Тем не менее, директива critical очень плоха для производительности и, вероятно, убьет большую часть (если не все) выгоды, получаемой от использования OpenMP в первую очередь.

#pragma omp atomic:

Директива atomic очень похожа на директиву critical. Основное отличие состоит в том, что, хотя директива critical применяется ко всему, что вы хотели бы сделать по одному потоку за раз, директива atomic применяется только к операциям чтения / записи памяти. Поскольку все, что мы делаем в этом примере кода, - это чтение и запись для суммирования, эта директива будет работать отлично:

#pragma omp parallel for schedule(static)
for(i = 0; i < snum; i++) {
    int *tmpsum = input + i;
#pragma omp atomic
    sum += *tmpsum;
}

Производительность atomic обычно значительно лучше, чем у critical. Тем не менее, это еще не лучший вариант в вашем конкретном случае.

reduction:

Метод, который вы должны использовать, и метод, который уже был предложен другими, - это reduction. Вы можете сделать это, изменив for -loop на:

#pragma omp parallel for schedule(static) reduction(+:sum)
for(i = 0; i < snum; i++) {
    int *tmpsum = input + i;
    sum += *tmpsum;
}

Команда reduction сообщает OpenMP, что, хотя цикл работает, вы хотите, чтобы каждый поток отслеживал свои собственные sum и добавить их все в конце цикла. Это самый эффективный метод, так как весь цикл теперь выполняется параллельно, при этом единственные служебные данные находятся прямо в конце цикла, когда необходимо добавить значения sum каждого из потоков.

8
ответ дан wolfPack88 27 August 2018 в 05:41
поделиться

Используйте предложение reduction ( в MSDN ).

int* input = (int*) malloc (sizeof(int)*snum);
int sum = 0;
int i;
for(i=0;i<snum;i++){
    input[i] = i+1;
}
#pragma omp parallel for schedule(static) reduction(+:sum)
for(i=0;i<snum;i++)
{
    sum += input[i];
}
3
ответ дан NikolayKondratyev 27 August 2018 в 05:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: