Пока IceLake8380 не доступен, промерял на IceLake8360Y. OMP_NUM_THREADS=40, AVX2: serial: 228 сек, 699000000 ячеек/с serial_nowrt: 374 сек, 427000000 ячеек/с openmp: 6 сек, 26087000000 ячеек/с openmp_nowrt: 11 сек, 14517000000 ячеек/с
Без default медленнее.Case для nowrt выглядит так:
select case (s)
case (3)
m2 (i, j) = 1
case (2)
m2 (i, j) = m1 (i, j)
case default
! m2 (i, j) = 0
end select
Вроде бы разгрузили цикл, убрали частую запись, а стало хуже. Как так? А теперь правильный ответ.
После того, как мы убрали default компилятор решил что цикл стал слишком простым для векторизации и не заходел ее делать. Но у нас есть стредства. Добавим -vec-threshold0 в ключи. И еще уберем точки. Вообще, т.к. чистить их теперь некому, а если не чистить то поле быстро забивается точками и default перестает работать.
ток, соответствующий сигналу в цифровых схемах, всегда течёт только между двумя точками
Прощайте шинные и параллельные схемы. Если вы возьмете какую нибудь мелкую микросхему (например народной 155 или любой другой серии), то внезапно вы обнаружите что там есть "нагрузочная способность" или коэффициент разветвления. Он как раз показывает сколько входов можно подключить к одному выходу. Так что две точки - это ваши фантазии.
Когда ядро 1 читает элемент массива из своего кеша L1, то надо сначала убедиться, что ни одно из других ядер не записало новое значение этого элемента в свой кеш L1.
Тоесть в вашем представлении каждое чтение из памяти предваряется обходом всех ядер процессора с вопросом - "слышь мужик, ты вот сюда ничего не писал?" Нет, это не так работает. Вики, MESI и так далее.
>> но схемотехнически параллельный доступ на чтение тоже является конфликтной ситуацией С чего бы это? Да и не забывайте что L1 и L2 у каждого ядра - свой.
Ваши виртуальные адреса кэшу не интересны, он работает с физическими, для него нет разницы - один процесс обращается к памяти или разные. Да и какие там конфликты? Если бы у вас был один массив, из которого вы читали и в который же писали - тогда да. Атомики или синхронизация нужна. А так у вас из одной кучи читается, в другую пишется, никто из потоков не может перезаписать уже записанную ячейку. Конфликтов 0.
Kind массива данных не менялся. Типы счетчиков времени и переменные границ увеличены до 8 байт, иначе считало отрицательное "ячеек/с", что как бы не комильфо.
6кх6к размер задачи. Переписанная инициализация на параллельный цикл, чтобы убрать нума-эффекты. Пиннинг процессов. Теперь вопрос, а как coarrays помогут нам разогнать кэш? Раз дело в нем?
Я напомню что мы меряем не абсолютную скорость, а относительную -параллельный код против последовательного. И в последовательном варианте будет тот же медленый алу (как вы утверждаете) против быстрого кэша.
Ну тоесть если я сделаю 39х ускорение на этом коде (немного отложим на хвосты) - вы возьмете свои слова обратно? :) При этом естесственно я могу изменять размер задачи.
Так уже занято Эпплом ;)
Да уж, ждем вместо Пульгынбёль 3.0 Путингынбёль 1.0.
Вы журналист или флюгер?
Разобрался:
¯\_(ツ)_/¯
Пока IceLake8380 не доступен, промерял на IceLake8360Y.
OMP_NUM_THREADS=40, AVX2:
serial: 228 сек, 699000000 ячеек/с
serial_nowrt: 374 сек, 427000000 ячеек/с
openmp: 6 сек, 26087000000 ячеек/с
openmp_nowrt: 11 сек, 14517000000 ячеек/с
Без default медленнее.Case для nowrt выглядит так:
Вроде бы разгрузили цикл, убрали частую запись, а стало хуже. Как так?
А теперь правильный ответ.
После того, как мы убрали default компилятор решил что цикл стал слишком простым для векторизации и не заходел ее делать. Но у нас есть стредства. Добавим -vec-threshold0 в ключи. И еще уберем точки. Вообще, т.к. чистить их теперь некому, а если не чистить то поле быстро забивается точками и default перестает работать.
serial: 230 сек, 692000000 ячеек/с
serial_nowrt: 204 сек, 780000000 ячеек/с
Ну вот, теперь другое дело.
С openmp_nowrt повожусь попожзе, там внезапно возникает куча точек :)
Я бы начал копать в сторону Даши. Двойная жизнь, любовник-игроман, тяжелые вещества, кто знает что там у нее?
Хорошо, сделаю. Ваш прогноз - какую цифру мы увидим?
И компилятор обмануть, который увидит что результат никуда не сохраняется и пройдется по всему этому dead code ellimination
Т.е. ситуации когда один передатчик и множество приемников - не бывает? Ну ну..
Где я его вижу? Оверхеда по чтению нет. Оверхед идет по записи, и то довольно сильно ограничен снуп-кэшами.
Прощайте шинные и параллельные схемы. Если вы возьмете какую нибудь мелкую микросхему (например народной 155 или любой другой серии), то внезапно вы обнаружите что там есть "нагрузочная способность" или коэффициент разветвления. Он как раз показывает сколько входов можно подключить к одному выходу. Так что две точки - это ваши фантазии.
Тоесть в вашем представлении каждое чтение из памяти предваряется обходом всех ядер процессора с вопросом - "слышь мужик, ты вот сюда ничего не писал?"
Нет, это не так работает. Вики, MESI и так далее.
Извините, ошибся уровнем комментариев О_о
>> но схемотехнически параллельный доступ на чтение тоже является конфликтной ситуацией
С чего бы это? Да и не забывайте что L1 и L2 у каждого ядра - свой.
Ваши виртуальные адреса кэшу не интересны, он работает с физическими, для него нет разницы - один процесс обращается к памяти или разные.
Да и какие там конфликты? Если бы у вас был один массив, из которого вы читали и в который же писали - тогда да. Атомики или синхронизация нужна. А так у вас из одной кучи читается, в другую пишется, никто из потоков не может перезаписать уже записанную ячейку. Конфликтов 0.
Чуть менее чем никак. Те же ядра, те же кэши. От того что данные у вас не в потоке, а в отдельном процессе ничего не поменяется.
Kind массива данных не менялся. Типы счетчиков времени и переменные границ увеличены до 8 байт, иначе считало отрицательное "ячеек/с", что как бы не комильфо.
6кх6к размер задачи. Переписанная инициализация на параллельный цикл, чтобы убрать нума-эффекты. Пиннинг процессов.
Теперь вопрос, а как coarrays помогут нам разогнать кэш? Раз дело в нем?
Ну пожалста:
export OMP_NUM_THREADS=40
rm -f *.bin
rm -f *.txt
ifort -fpp -O3 -xAVX2 ./life_serial.f90 -o ./life_serial.bin -DFOUT='life_serial.txt'
./life_serial.bin
export KMP_AFFINITY=scatter,granularity=fine
ifort -fpp -O3 -xAVX2 -parallel -fopenmp ./life_openmp.f90 -o ./life_openmp.bin -DFOUT='life_openmp.txt'
./life_openmp.bin
Я напомню что мы меряем не абсолютную скорость, а относительную -параллельный код против последовательного. И в последовательном варианте будет тот же медленый алу (как вы утверждаете) против быстрого кэша.
Какие-какие... Про невозможность 40х и когерентность кешей как причину недостижимости
Ну тоесть если я сделаю 39х ускорение на этом коде (немного отложим на хвосты) - вы возьмете свои слова обратно? :) При этом естесственно я могу изменять размер задачи.