Гиперпоточность… сделала мой рендерер в 10 раз медленнее

Краткое изложение : Как можно указать в его коде, что OpenMP должен использовать потоки только для НАСТОЯЩИХ ядер, то есть не считать гиперпотоковые?

Подробный анализ : На протяжении многих лет я кодировал только SW, открытые исходный рендерер (растеризатор / трассировщик лучей) в свободное время. Код GPL и двоичные файлы Windows доступны здесь: https://www.thanassis.space/renderer.html Он компилируется и отлично работает под Windows, Linux, OS / X и BSD.

В прошлом месяце я представил режим трассировки лучей - и качество создаваемых изображений взлетело до небес. К сожалению, трассировка лучей на порядки медленнее, чем растеризация. Для увеличения скорости, как и для растеризаторов, я добавил поддержку OpenMP (и TBB) в трассировщик лучей - чтобы легко использовать дополнительные ядра ЦП. И растеризация, и трассировка лучей легко поддаются распараллеливанию (работа на треугольник - работа на пиксель).

Дома, с моим Core2Duo, второе ядро ​​помогало во всех режимах - и растеризация, и режим трассировки лучей получили ускорение, которое находится между 1.85x и 1.9x.

Проблема: Естественно, мне было любопытно увидеть максимальную производительность процессора (я также «играю» с графическими процессорами, предварительный порт CUDA ), поэтому мне нужна была прочная база для сравнений. Я дал код своему хорошему другу, у которого есть доступ к «звериной» машине с 16-ядерным суперпроцессором Intel за 1500 $.

Он запускает его в «самом тяжелом» режиме, режиме трассировки лучей. ..

... и он получает пятую часть скорости моего Core2Duo (!)

Гасп - ужас. Что только что произошло?

Мы начали пробовать различные модификации, патчи ... и, в конце концов, это выяснили.

Используя переменную среды OMP_NUM_THREADS, можно контролировать количество порождаемых потоков OpenMP. Что только что произошло?

Мы начали пробовать различные модификации, патчи ... и, в конце концов, это выяснили.

Используя переменную среды OMP_NUM_THREADS, можно контролировать количество порождаемых потоков OpenMP. Что только что произошло?

Мы начали пробовать различные модификации, патчи ... и, в конце концов, это выяснили.

Используя переменную среды OMP_NUM_THREADS, можно контролировать количество порождаемых потоков OpenMP. По мере увеличения количества потоков от 1 до 8 скорость увеличивалась (близка к линейному увеличению). В тот момент, когда мы пересекли 8, скорость начала снижаться, пока не упала до одной пятой скорости моего Core2Duo, когда использовались все 16 ядер!

Почему 8?

Потому что 8 было номером реальных ядер. Остальные 8 были ... гиперпоточными!

Теория: Это было новостью для меня - я видел, как гиперпоточность сильно помогает (до 25%) в других алгоритмах, так что это было неожиданно. Очевидно, хотя каждое ядро ​​с гиперпоточностью имеет свои собственные регистры (и модуль SSE?), Трассировщик лучей не может использовать дополнительную вычислительную мощность. Что заставляет меня задуматься ...

Вероятно, не хватает вычислительной мощности - это пропускная способность памяти.

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

18
задан ttsiodras 1 June 2016 в 18:43
поделиться