Слушаемое будущее на будущее Скала

Как уже объяснялось, предположение о том, что 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.

30
задан vptheron 2 August 2013 в 21:46
поделиться