23.01.2021

Отгадка

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

Между тем, есть очень простой способ проверить, что является причиной – взять, да и отключить HyperThreading. Что я собственно и сделал на AMD Ryzen 3600.
Отключить-то я его отключил, а вот назад он включаться не захотел, да. На материнке ASRock B450M Steel legend. Давненько я с такими глюками не сталкивался.
Погуглил. Простые советы не помогли, оставался последний способ - сбросить BIOS. И тут меня перемкнуло, и я решил сбросить BIOS жестко, перемкнув соответствующие контакты на материнской плате. Перемычки под рукой не оказалось, поэтому замыкал контакты имеющимися под руками металлическими предметами, строго по инструкции, на 5 секунд.
Несколько попыток не помогли
– BIOS не сбрасывался. Я уж чуть было не разобрал полкомпьютера, пытаясь добраться до батарейки CMOS-памяти, да вовремя остановился. Достаточно оказалось сбросить BIOS программно.😅

Итак, результаты. Все же виной падению производительности оказалась нехватка памяти. Потоки запускались не абсолютно синхронно, а завершались очень быстро, поэтому замерялось не столько время выполнения, сколько время реакции планировщика OS.

Посмотрим графики. "12/12" – 12 потоков на 12 виртуальных ядрах из 6 физических; "6/6" 6 потоков на 6 физических ядрах; "6/12" 6 потоков на 12 виртуальных ядрах.
Кстати, там есть любопытный момент.



Сначала банальность: в однопоточном режиме HyperThreading никак не влияет на производительность.

В многопоточном HyperThreading безусловно хорошо повышает общую производительность, пока решаемая задач целиком попадает в кэш L3.
Но при этом производительность каждого потока оказывается немного меньше, чем при отключенном HyperThreading. Насколько меньше? Примерно на 4-5% для каждого потока, и до 30% на шести потоках в целом (по одному потоку на физическое ядро).
Это хорошо видно на графиках "6/62 и "6/12". Последний проигрывает первому на всех размерностях.

О чем это говорит? О том, что без HyperThreading отзывчивость приложения может быть лучше. Потенциально до 30%, но гораздо ближе к практике  5% в силу параллельности решения задачи.
Сомневаюсь, что эти 5% заметит даже самый требовательный игрок, но в каких-то вариантах эти 5% могут все же иметь значение.

Еще одной причиной для отключения HyperThreading может быть отсутствие работы для такого большого количества виртуальных ядер плюс некоторые снижение теплопакета при максимальной загрузке.

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

2 комментария:

  1. Молодцы! Поздравляю, все-таки докопались до истины, чуть компьютер нет угробили :)

    Похоже действительно планировщик Windows почему-то не различает ядра и потоки и при 6/12 иногда запускает 2 потока на одном ядре.

    При размерности 96 для float и 48 для double разрыв между 6/6 и 6/12 увеличивается, как я понимаю, в следствии нехватки места в L1 кэше для двух СЛАУ?

    А при 192 уравнениях конвейер наконец-то начинает работать по полной, и для HyperThreading-га не остается свободных FPU блоков?

    ОтветитьУдалить
  2. Да ладно, он железный, его трудно угробить )

    Согласен, видимо, все обстоит так, как ты говоришь, про кэш и про конвейер.

    ОтветитьУдалить