Сравнительный анализ параллельных вычислений OpenMP

Я пытаюсь сравнить вычисление f(x), меняя количество потоков на каждой итерации.

f(x) = c * ln(x) * cos(x)

n=10000000


for (int pp = 2; pp<17; pp++)
{
    p = pp;
    int chunk = n/p; //acts like floor
    omp_set_num_threads(p);
    double start_parallel = omp_get_wtime();
    //start parallel
    #pragma omp parallel shared(tt,chunk) private (i)
    {
        //printf("thread number %d\n",omp_get_thread_num());
        #pragma omp for schedule(dynamic,chunk) nowait
        for(i=0; i<n; i++)
        {
            //tt[i] = f(tt[i]);
            tt[i] = f1(tt[i]); //the speed up is much higher with f1 since log and cos 
                               //computations are polynomial; see function.
        }
    } //end parallel
    double end_parallel = omp_get_wtime();
    double cpu_time_used_parallel = (double) (end_parallel - start_parallel);
    printf("parallel: for n=%d, p=%d, time taken=%f, speedup=%f\n",
            n,p,cpu_time_used_parallel,
            cpu_time_used_seq/cpu_time_used_parallel);
}

Результат:

Начал менять темы:

параллельно: для n=10000000, p=2, затраченное время=0,153774, ускорение=3,503831

параллельно: для n=10000000, p=3, затраченное время=0,064447, ускорение=8,360370

параллельно: для n=10000000, p=4, затраченное время=0,044694, ускорение=12,055239

параллельно: для n=10000000, p=5, затраченное время=0,048700, ускорение=11,063550

параллельно: для n=10000000, p=6, затраченное время=0,039009, ускорение=13,811989

параллельно: для n=10000000, p=7, затраченное время=0,041735, ускорение=12,910017

параллельно: для n=10000000, p=8, затраченное время=0,041268, ускорение=13,055919

параллельно: для n=10000000, p=9, затраченное время=0,039032, ускорение=13,804157

параллельно: для n=10000000, p=10, затраченное время=0,038970, ускорение=13,825767

параллельно: для n=10000000, p=11, затраченное время=0,039843, ускорение=13,522884

параллельно: для n=10000000, p=12, затраченное время=0,041356, ускорение=13,028237

параллельно: для n=10000000, p=13, затраченное время=0,041039, ускорение=13,128763

параллельно: для n=10000000, p=14, затраченное время=0,047433, ускорение=11,359218

параллельно: для n=10000000, p=15, затраченное время=0,048430, ускорение=11,125202

параллельно: для n=10000000, p=16, затраченное время=0,051950, ускорение=10,371477


Примечание. Ускорение здесь вычисляется по последовательному алгоритму (потоки = 1).

Изменение p (количество потоков) не влияет на ускорение.

Правильно ли я делаю это, или причина связана с неэффективным увеличением количества потоков (т.е. теоретически изменение p серьезно не повлияет на O(myprogram) )?


person Oussama Ben Ghorbel    schedule 04.10.2019    source источник


Ответы (2)


В : Правильно ли я делаю...?
О : Нет, извините, вы случайно не сделали это право. Давайте проанализируем причины и вместе наметим несколько советов по сравнительному тестированию производительности класса HPC:

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

введите здесь описание изображения

Причины?

Код имеет огромные дополнительные накладные расходы по сравнению с частью «вычислений». Это самый сильный признак ошибочного использования технологических возможностей конструктора синтаксиса, который в остальном является законным ( OpenMP здесь, map-reduce где-то еще, list-comprehension в других случаях или какие-то другие трюки с синтаксисом где-то еще)

Окончательная производительность — это искусство балансирования (правильный баланс затрат и выгод — любой вид дисбаланса означает потерю преимущества в производительности).


Расходы? Здесь? Посмотрите на ландшафт результатов ::

Вторым грехом было игнорирование «закулисного» штрафа за [TIME]-домен за масштабирование [SPACE]-домена. Чем больше n, тем больше памяти должно было быть выделено, и тем больше штрафов возникало из-за (ужасающей) неэффективности строки кэша, и все это имело нулевую защиту от попадания в адскую подкачку памяти. :

n=1E3        1E4        1E5        1E6        1E7        1E8        1E9       :
______________________________________________________________________________:_____
1.000      1.000      1.000      1.000      1.000      1.000      1.000       : p= 1
0.930      1.403      0.902      1.536      1.492      1.517      0.356       : p= 2
1.075      2.319      2.207      1.937      2.001      1.991      1.489++     : p= 3
1.497+++++ 2.636++++  1.563      1.657      2.571      2.144      0.687       : p= 4
1.226++    2.548+++   0.957      2.025      2.357      1.731      1.569++++   : p= 5
1.255+++   1.805      2.704      2.020      2.348      1.502      0.989       : p= 6
0.957      0.581      3.104++    2.124      2.486      2.002      0.838       : p= 7
1.151      1.376      2.449      2.154      2.573      1.536      0.776       : p= 8
1.135      1.685      2.388      2.506+++   2.852++++  2.311      1.676+++++  : p= 9
1.285++++  2.492++    2.497      2.568++++  2.647+     2.467      1.413+      : p=10
1.177      2.314+     2.709+     2.174      2.688+++   2.634++++  0.606       : p=11
1.216+     2.293      2.442      2.287      2.550      2.551++    1.256       : p=12
1.034      2.148      1.802      2.361++    2.635      2.554+++   1.181       : p=13
0.999      0.440      3.672+++++ 2.774+++++ 2.927+++++ 2.839+++++ 1.496+++    : p=14
1.091      1.217      3.285++++  2.284      2.525      2.356      1.005       : p=15
0.937      2.850+++++ 3.185+++   2.334+     2.655++    2.508+     0.889       : p=16

Советы по повышению производительности?

  • При проведении сравнительных вычислений сравните вычисления и избегайте MEM-I/O

  • При сравнительном анализе всегда проверяйте всю картину, чтобы почувствовать (лучше узнать, как избежать/устранить любое подобное искажение измеренных результатов) в -cache побочные эффекты

  • Всегда избегайте какой-либо формы совместного использования (можно избежать - сопоставьте обработку с разрозненными областями tt[], но покрывая "все" tt[] в согласованных блоках строки кэша, поэтому чтобы избежать ложного обмена и «по крайней мере» повторно использовать любые данные из уже извлеченных блоков данных, которые вы уже оплатили за выборку MEM-I/O (если загрузка/сохранение на основе вектора действительно является обязательным - см выше)

  • Разрешайте и активно используйте любые приемы векторизации высокопроизводительных вычислений, доступные с FMA4 / SIMD / AVX512.

person user3666197    schedule 06.10.2019
comment
Это выдающийся ответ, там много хороших моментов. Если сравнивать вычисления, сравните вычисления и избегайте MEM-I/O да, я сам понял это вчера, спасибо, что указали на это! Хотя я все еще новичок в openmp и параллельных вычислениях, так что большая часть этого не имеет смысла. Тем не менее, большое спасибо за то, что просветили меня таким количеством информации. - person Oussama Ben Ghorbel; 07.10.2019
comment
Хороший ответ. Есть еще одна вещь, которую вы упустили. Запуск новой команды потоков после изменения количества потоков OpenMP — затратная операция по сравнению с запуском параллельного региона с тем же количеством потоков, что и раньше. Поскольку реальные коды не изменяют (или, по крайней мере, не должны) изменять степень параллелизма, эталонный тест должен запускать пустой, не синхронизированный, прогревающий параллельный регион перед запуском синхронизированного. - person Jim Cownie; 07.10.2019
comment
@JimCownie Хороший разговор на SC-18, здорово читать о модели MPAS-Ocean (кстати, насколько хорошо она вписывается в наблюдаемую реальность метастабильных явлений, например, точность имитации длинной временной шкалы (по сравнению с dt в шаг моделирования в области [ВРЕМЕНИ]) макромасштабные (несколько тысяч квадратных километров) реконфигурации морских потоков между двумя метастабильными состояниями, названными Куросио и Оясио соответственно? Если бы этот уровень детализации был достижения в этом высокоточном моделировании, команды Министерства энергетики заслуживают величайшего восхищения, я снимаю шляпу за поддержку этих усилий, сэр. - person user3666197; 07.10.2019
comment
@user366197 user366197 Чтобы узнать подробности о MPAS, поговорите с настоящими учеными; Я просто ученый-компьютерщик, языковой юрист и разработчик времени выполнения :-) - person Jim Cownie; 08.10.2019
comment
@JimCownie Вы меня, сэр, обслуживаете в основном домен конечного автомата (независимо от того, насколько он богат, но конечен) в качестве юриста по синтаксису: o) Всего наилучшего, Джим, и спасибо за добавление ваших замечаний о том, как избежать добавления -затраты на (повторное) создание omp-потоков из-за искажения временных разделов кода OpenMP выше. Стандарт OpenMP не определяет базовое средство выполнения; это исключительно проблема реализации. Реализация OpenMP может выбрать предоставление этой абстракции любым из множества способов, т. е. одна реализация может отображать поток OpenMP на процесс O/S, другая реализация Pthread. - person user3666197; 08.10.2019
comment
@user3666197 user3666197 Если это приведет вас в Денвер в следующем месяце на SC19, я буду рядом, и меня можно будет найти на стенде OpenMP. (Здесь мы отклоняемся от темы, но я не вижу возможности отправлять личные сообщения...) - person Jim Cownie; 08.10.2019
comment
Ребята, еще одна деталь, в цикле, где я варьирую количество потоков, первая итерация +- приличный бенчмаркинг, остальное НЕПРАВИЛЬНО. Почему? Потому что есть выборка значения из кеша. Чтобы очистить кеш: я добавил цикл, в котором я снова помещал случайные значения в массив, и скорость снизилась до 2 ~ 3. - person Oussama Ben Ghorbel; 08.10.2019
comment
Еще одна деталь, не стесняйтесь открывать новый вопрос — StackOverflow настоятельно не рекомендует углубляться в определение O/P или добавлять еще одно, еще одно, еще одно и еще одно. наконец, последний вопрос. Члены сообщества всегда рады опубликовать новую проблему, сформулированную в MCVE, со всеми соответствующими подробностями о WHYTSF- - -Wчто Hсохранить, Yвы пытались Sо Far, возможно, с URL-адресом состояния сеанса живого кода в IDE, например tio.run/# c-gcc или godbolt.org/z/7Amgc9. С нетерпением ждем новых идей высокопроизводительных вычислений в действии - person user3666197; 08.10.2019

Ваши результаты неверны из-за предложения nowait в прагме omp. Обычно конец parallel представляет собой точку синхронизации, но без ожидания первый завершившийся поток не будет ждать других потоков, поэтому вы будете выполнять double end_parallel = omp_get_wtime();, пока другие потоки все еще выполняют какие-то вычисления. Если вы удалите nowait, вы увидите совершенно другие результаты.

person coyotemk    schedule 04.10.2019
comment
Я не уверен в этом, синхронизация происходит в конце первой директивы omp parallel. Ни один поток, кроме основного, не достигает end_time сам по себе, только основной поток попадает туда и суммирует время? - person Oussama Ben Ghorbel; 07.10.2019