3

Я только что написал свою первую программу OpenMP, которая распараллеливает простой цикл. Я запустил код на своей двухъядерной машине и увидел некоторую скорость при переходе от 1 потока к 2 потокам. Тем не менее, я запустил тот же код на школьном Linux-сервере и не видел ускорения. Пробовав разные вещи, я наконец понял, что удаление некоторых бесполезных заявлений printf привело к значительному ускорению кода. Ниже приводится основная часть кода, который я распараллеливание:Нет ускорения с использованием бесполезных printf с использованием OpenMP

#pragma omp parallel for private(i) 
for(i = 2; i <= n; i++) 
{ 
    printf("useless statement"); 
    prime[i-2] = is_prime(i); 
} 

Я думаю, что реализация Printf имеет значительные накладные расходы, что OpenMP должен быть дублирующий каждой нити. Что вызывает эти накладные расходы и почему OpenMP не может его преодолеть?

+0

Не выдерживает; слышал о Prime Sieve? http://en.wikipedia.org/wiki/Generating_primes#Prime_sieves – Will

+0

Какой компилятор вы используете? Какая версия? – osgx

ответ

6

Спекуляция, но, может быть, стандартная защита охраняется замком?

В общем, Printf является дорогостоящей операцией, так как она взаимодействует с другими ресурсами (например, файлы консоли и такие).

Мой эмпирический опыт заключается в том, что printf очень медленный на консоли Windows, сравнительно значительно быстрее на консоли Linux, но быстрее всего, если перенаправлен на файл или/dev/null.

Я обнаружил, что Printf-отладка может серьезно повлиять на производительность моих приложений, и я использую его экономно.

Попробуйте запустить приложение перенаправлен в файл или в/DEV/нуль, чтобы увидеть, если это имеет какое-либо заметное влияние; это поможет сузить место, где лежит проблема.

Конечно, если printfs бесполезны, почему они в цикле вообще?

+1

Печать была там для целей отладки. – t2k32316

+1

Да, glibc охраняет stdout с замками, так как он его буферизует. – osgx

3

Чтобы расширить немного на @ ответ Уилла ...

Я не знаю, является ли стандартный вывод охранял замок, но я уверен, что запись на него сериализации в какой-то момент в программном обеспечении стек. С включенными операциями printf OP, вероятно, синхронизирует выполнение большого количества последовательных записей в stdout, а не с параллельным выполнением цикла.

Я предлагаю, что ОП изменяет инструкцию printf, чтобы включить i, посмотреть, что произойдет.

Что касается кажущегося ускорения на двухъядерной машине - это было статистически значимым?

+0

Очевидное ускорение не было показано статистически сильным образом. Я только что запустил его и провел несколько прогонов около 9 секунд с 1 нитью и 7 секундами с двумя потоками. Но когда я запускал его на серверах моей школы, не было явно никакого ускорения (пока я не избавился от заявлений printf). Я думаю, что мой главный вопрос прямо сейчас является лишь одним из любопытства: что происходит за кулисами с printf, что помешает OMP распараллелить цикл for? Я полагаю, это просто, как вы сказали: он должен быть сериализован в конце концов ... – t2k32316

+1

+1; Будет правильно, что printf() является очень дорогостоящей операцией, но это на самом деле поможет ускорить, а остальные останутся равными; Независимые дорогостоящие задачи хорошо распараллеливаются. Решающий вопрос - если они действительно независимы. Как говорит Марк, они обращаются к общему ресурсу (stdout), поэтому на определенном уровне материал должен быть сериализован, и сериализация неизбежно приводит к параллельной производительности. –

0

Каковы были ваши тайминги - было ли это намного медленнее с печатью? В некоторых жестких циклах printf может занимать значительную часть общего вычислительного времени; например, если is_prime() довольно быстро, и поэтому производительность определяется больше количеством вызовов printf, чем количеством (параллельных) вызовов is_prime().

1

Вы здесь параллель для цикла, но планирование не определен.

#pragma omp parallel for private(i) 
for(i = 2; i <= n; i++) 

Существует несколько типов планирования, определенных в стандарте OpenMP 3.0.Их можно изменить, установив переменную OMP_SCHEDULE окружения type[,chunk] где

  • типа является одним из статического, динамический, руководствоваться или авто
  • кусок является дополнительным положительным целое число, которое определяет размер куска

Другой способ изменения вида расписания - вызов функции openmp omp_set_schedule

Функция is_prime может быть довольно быстрой./Предлагаю/

prime[i-2] = is_prime(i); 

Таким образом, проблема может пришел из режима неправильного планирования, когда небольшое число выполняется перед барьером от планирования.

И printf имеют 2-х части внутри него/Я считаю Glibc как реализация популярного Linux LibC/

  1. Обработать строку формата и поместить все параметры в буфер
  2. запись буфер в файл с дескриптором (в FILE буфер , как и стандартный вывод буферизуются Glibc по умолчанию)

Первая часть Printf может быть сделана параллельно, но вторая часть представляет собой критический участок, и он заблокирован с _IO_flockfile.

Смежные вопросы