Я оптимизировал трассировку лучей, и, чтобы получить хорошую скорость, я использовал OpenMP, как показано ниже (C ++):
Accelerator accelerator; // Has the data to make tracing way faster
Rays rays; // Makes the rays so they're ready to go
#pragma omp parallel for
for (int y = 0; y < window->height; y++) {
for (int x = 0; x < window->width; x++) {
Ray& ray = rays.get(x, y);
accelerator.trace(ray);
}
}
Я получил производительность в 4,85 раза в 6-ядерном / 12-поточном потокеЦПУ.Я думал, что получу больше, чем, может быть, что-то вроде 6-8x ... особенно, когда это израсходует> = 99% времени обработки приложения.
Я хочу узнать, где моя производительностьУзкое место есть, поэтому я открыл VTune и профилировал.Обратите внимание, что я новичок в профилировании, поэтому, возможно, это нормально, но вот график, который я получил:
В частности, это второй по величинепотребитель времени:
, где 58% - это использование микроархитектуры.
Пытаясь решить эту проблему самостоятельно, я пошел искатьза информацией об этом, но больше всего я мог найти на вики-страницах Intel VTune:
Среднее использование физического ядра
Описание метрики
Метрика показывает среднюю физическую нагрузкуиспользование ядер при вычислениях приложения.Время вращения и накладные расходы не учитываются.Идеальное среднее использование ЦП равно количеству физических ядер ЦП.
Я не уверен, что это пытается мне сказать, что приводит меня к моему вопросу:
Это нормально для такого результата?Или где-то что-то идет не так? Можно ли увидеть ускорение в 4,8 раза (по сравнению с теоретическим максимумом 12,0) для чего-то смущающе параллельного?Хотя сама трассировка лучей может быть недружественной из-за лучей, отражающихся повсюду, я сделал все возможное, чтобы сжать память и сделать ее максимально удобной для кэширования, использовать библиотеки, использующие SIMD для вычислений, выполнил бесчисленные реализации из литературы, чтобы ускорить процесс.и избегать разветвлений в максимально возможной степени и не делать рекурсии.Я также распараллелил лучи так, чтобы не было ложного совместного использования AFAIK, поскольку каждая строка выполняется одним потоком, поэтому не должно быть никакой записи строки кэша для каких-либо потоков (тем более, что обход луча - все const
).Кроме того, фреймбуфер имеет мажорную строку, поэтому я надеялся, что ложное совместное использование не станет для этого проблемой.
Я не знаю, будет ли профилировщик работать с главным циклом, который связан с OpenMP, и этоожидаемый результат, или если у меня есть какая-то ошибка новичка, и я не получаю желаемую пропускную способность.Я также проверил, что он порождает 12 потоков, и OpenMP делает.
Я полагаю, др, я облажался с использованием OpenMP?Исходя из того, что я понял, предполагается, что среднее использование физического ядра будет выше среднего уровня использования логического ядра, но я почти наверняка не понимаю, о чем говорю.