OpenMP вложенное странное поведение [дубликат]

Повторение решения первого сообщения более абстрактным образом:

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> while 2 in x: x.remove(2)
>>> x
[1, 3, 4, 3]
6
задан R. Yoder 12 November 2015 в 02:57
поделиться

2 ответа

Извините, ваш профессор ошибся. Вы должны использовать взаимное исключение или некоторые другие барьеры, чтобы гарантировать непрерывное использование общего ресурса (который в данном случае является выходным файлом STDOUT).

Смешанный вывод - потенциально ожидаемое поведение, независимо от printf или std::cout::operator<<(). Различия в поведении, которые вы видите, - это тонкие различия в продолжительности исполнения каждого из-за их различного дизайна. Вы должны ожидать этого поведения в любом случае.

Я просто не понимаю, почему он будет работать для всех остальных.

Это не так. Будьте героем своего класса и объясните, как он работает и как его исправить. Скажите им, что они посылают свою любовь. :)

7
ответ дан Brian Cain 22 August 2018 в 04:31
поделиться

Как уже объяснялось, предположение о том, что printf() является атомарным и не будет искажать ваш результат, тогда как std::cout::operator<<() не является и будет испортить вещи, если они в корне неверны.

Однако все еще существует (крошечная) часть «истины» в этом, но на другом уровне. Позвольте мне привести вам пример:

Если я попытаюсь использовать C-стиль OpenMP «Hello world», который может дать это:

printf( "Hello from thread %d of %d\n",
         omp_get_thread_num(),
         omp_get_num_threads() );

Тот же самый стиль C ++ может выглядеть например:

std::cout << "Hello from thread " << omp_get_thread_num()
          << " of " << omp_get_num_threads()
          << std::endl;

И существенное различие между ними заключается в том, что для printf() я вызываю только метод печати один раз, с полностью подготовленной выходной строкой, тогда как в стиле C ++ std::cout::operator<<() 5 раз, только с битами и частями строк, которые могут быть отправлены или не отправлены на стандартный вывод. Внутри все может случиться, и я не буду пытаться совершать какие-либо действия. Но, по крайней мере, используя здесь printf(), я увеличиваю свои шансы на чистый вывод, даже если я не могу этого гарантировать.

Вот полный пример:

#include <iostream>
#include <stdio.h>
#include <omp.h>

int main() {
    #pragma omp parallel
    printf( "Hello from thread %d of %d with printf()\n",
             omp_get_thread_num(),
             omp_get_num_threads() );

    printf( "*** outside of parallel region ***\n" );

    #pragma omp parallel
    std::cout << "Hello from thread " << omp_get_thread_num()
              << " of " << omp_get_num_threads()
              << " with std::cout"
              << std::endl;
    return 0;
}

Какой на моем Linux-ноутбуке дает мне (GCC 5.2):

~/tmp$ g++ -fopenmp stdout.cc
~/tmp$ ./a.out 
Hello from thread 3 of 4 with printf()
Hello from thread 0 of 4 with printf()
Hello from thread 2 of 4 with printf()
Hello from thread 1 of 4 with printf()
*** outside of parallel region ***
Hello from thread Hello from thread Hello from thread Hello from thread 1 of 4 with std::cout23 of 4 with std::cout
 of 4 with std::cout
0 of 4 with std::cout

~/tmp$

Если вы внимательно посмотрите, вы увидите, что ни один из индивидуальных звонков на std::cout::operator<<() не разбит, но каждый новый вызов - это возможность для различные потоки, чтобы разыгрывать друг друга, и получить выход из строя.

Итак, опять же, говоря, что printf() является атомарным и не испортит вещи, неправильно, но просто для сложного вывода string, он вряд ли будет искажен, чем с std::cout.

5
ответ дан Gilles 22 August 2018 в 04:31
поделиться
Другие вопросы по тегам:

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