我一直在优化光线跟踪器,并且为了获得更好的速度,我一般使用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);
}
}
我在6核/ 12线程CPU上获得了4.85倍的性能。我以为我会得到更多,也许是6到8倍...尤其是当它消耗了应用程序处理时间的99%以上时。
我想找出性能瓶颈在哪里,所以我打开了VTune并进行了概要分析。请注意,我是剖析的新手,所以也许这很正常,但这是我得到的图形:
特别是,这是第二大时间消耗者:
其中58%是微架构使用率。
尝试独自解决此问题,我一直在寻找有关此问题的信息,但我能找到的最多的是英特尔的VTune Wiki页面:
平均物理核心利用率
指标说明
该度量标准通过计算应用程序显示平均物理内核利用率。不计算旋转时间和开销时间。理想的平均CPU利用率等于物理CPU内核数。
我不确定这是想告诉我什么,这使我想到了我的问题:
这样的结果正常吗?还是某个地方出了问题?只能以4.8倍的速度(与理论上的最大值12.0相比)进行令人尴尬的并行处理吗?虽然光线跟踪本身可能会因光线反弹而变得不友好,但我已尽我所能来压缩内存并尽可能做到对缓存友好,使用利用SIMD进行计算的库,从文献中进行了无数次实现以加快处理速度,并尽可能避免分支并且不进行递归。我还并行化了光线,因此没有错误的共享AFAIK,因为每一行都是由一个线程完成的,因此不应为任何线程编写任何缓存行(特别是因为光线遍历都是const
)。另外,帧缓冲区是行主要的,因此我希望假共享不会成为问题。
我不知道探查器是否会选择使用OpenMP进行线程化的主循环,这是预期的结果,或者我是否遇到某种新手错误并且没有获得所需的吞吐量。我还检查了它产生了12个线程,而OpenMP产生了。
我猜是tl; dr,我在使用OpenMP搞砸了吗?从我收集的数据来看,平均物理核心利用率应该接近平均逻辑核心利用率,但是我几乎可以肯定不知道我在说什么。
答案 0 :(得分:1)
天哪,您做对了,您高估了并行执行的效率。您没有提供有关所使用的体系结构(CPU,内存等)的详细信息,也没有提供代码...但是要简单地说,我认为超出4.8倍的速度会达到内存带宽限制,因此RAM速度是你的瓶颈。
为什么?
正如您所说,光线跟踪并不难并行运行,而且您做得对,因此,如果CPU不是100%繁忙,我想您的内存控制器就是这样。 假设您正在跟踪RAM中的模型(三角形?体素?),则在检查命中时,射线需要读取模型的某些位。您应该检查最大RAM带宽,然后将其除以12(线程),然后除以每秒的射线数...然后发现,当跟踪大量射线时,即使40 GB / s也“不是那么多” 。因此,GPU是光线追踪的更好选择。
长话短说,我建议您尝试分析内存使用情况。