根据使用 OpenMP 时的 VTune,低 'Average Physical Core Utilization',不确定大图是什么
Low 'Average Physical Core Utilization' according to VTune when using OpenMP, not sure what the bigger picture is
我一直在优化光线追踪器,为了获得很好的加速,我通常使用 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 core/12 线程 CPU 上获得了 4.85 倍的性能。我以为我会得到更多,可能是 6-8 倍...尤其是当这占用 >= 99% 的应用程序处理时间时。
我想找出我的性能瓶颈在哪里,所以我打开了 VTune 并进行了分析。请注意,我是分析新手,所以这可能是正常的,但这是我得到的图表:
特别是,这是第二大时间消费者:
其中 58% 是微架构的使用。
为了自己解决这个问题,我开始寻找这方面的信息,但我能找到的最多的是英特尔的 VTune 维基页面:
Average Physical Core Utilization
Metric Description
The metric shows average physical cores utilization by computations of the application. Spin and Overhead time are not counted. Ideal average CPU utilization is equal to the number of physical CPU cores.
我不确定这是想告诉我什么,这引出了我的问题:
这样的结果正常吗?还是某处出了问题? 对于令人尴尬的并行情况,只看到 4.8 倍的加速(与理论最大值 12.0 相比)是否可以?由于光线到处弹跳,光线追踪本身可能不友好,但我已尽我所能压缩内存并尽可能对缓存友好,使用利用 SIMD 进行计算的库,从文献中进行了无数实现以加快速度,并尽可能避免分支,不做递归。我还并行化了光线,这样就不会出现错误的共享 AFAIK,因为每一行都由一个线程完成,所以不应该为任何线程写入任何缓存行(特别是因为光线遍历都是 const
)。帧缓冲区也是行主要的,所以我希望虚假共享不会成为问题。
我不知道探查器是否会选择使用 OpenMP 线程化的主循环,这是预期的结果,或者如果我有某种新手错误并且我没有获得我想要的吞吐量.我还检查它是否产生了 12 个线程,而 OpenMP 确实如此。
我猜 tl;dr,我是不是在使用 OpenMP 时搞砸了?根据我收集到的信息,平均物理核心利用率应该接近平均逻辑核心利用率,但我几乎肯定不知道我在说什么。
恕我直言,您做对了,您高估了并行执行的效率。您没有提供有关您正在使用的体系结构(CPU、内存等)的详细信息,也没有提供代码......但简单地说,我认为超过 4.8 倍的速度增加会达到内存带宽限制,所以内存速度是你的瓶颈。
为什么?
如您所说,光线追踪并不难 运行 并行并且您做对了,所以如果 CPU 不是 100% 忙,我猜您的内存控制器是.
假设您正在追踪 RAM 中的模型(三角形?体素?),您的光线需要在检查命中时读取模型的位。您应该检查您的最大 RAM 带宽,然后将其除以 12(线程),然后将其除以每秒的射线数...发现即使 40 GB/s 也是 "not so much" 当您跟踪很多时射线。这就是为什么 GPU 是光线追踪的更好选择。
长话短说,我建议您尝试分析内存使用情况。
我一直在优化光线追踪器,为了获得很好的加速,我通常使用 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 core/12 线程 CPU 上获得了 4.85 倍的性能。我以为我会得到更多,可能是 6-8 倍...尤其是当这占用 >= 99% 的应用程序处理时间时。
我想找出我的性能瓶颈在哪里,所以我打开了 VTune 并进行了分析。请注意,我是分析新手,所以这可能是正常的,但这是我得到的图表:
特别是,这是第二大时间消费者:
其中 58% 是微架构的使用。
为了自己解决这个问题,我开始寻找这方面的信息,但我能找到的最多的是英特尔的 VTune 维基页面:
Average Physical Core Utilization
Metric Description
The metric shows average physical cores utilization by computations of the application. Spin and Overhead time are not counted. Ideal average CPU utilization is equal to the number of physical CPU cores.
我不确定这是想告诉我什么,这引出了我的问题:
这样的结果正常吗?还是某处出了问题? 对于令人尴尬的并行情况,只看到 4.8 倍的加速(与理论最大值 12.0 相比)是否可以?由于光线到处弹跳,光线追踪本身可能不友好,但我已尽我所能压缩内存并尽可能对缓存友好,使用利用 SIMD 进行计算的库,从文献中进行了无数实现以加快速度,并尽可能避免分支,不做递归。我还并行化了光线,这样就不会出现错误的共享 AFAIK,因为每一行都由一个线程完成,所以不应该为任何线程写入任何缓存行(特别是因为光线遍历都是 const
)。帧缓冲区也是行主要的,所以我希望虚假共享不会成为问题。
我不知道探查器是否会选择使用 OpenMP 线程化的主循环,这是预期的结果,或者如果我有某种新手错误并且我没有获得我想要的吞吐量.我还检查它是否产生了 12 个线程,而 OpenMP 确实如此。
我猜 tl;dr,我是不是在使用 OpenMP 时搞砸了?根据我收集到的信息,平均物理核心利用率应该接近平均逻辑核心利用率,但我几乎肯定不知道我在说什么。
恕我直言,您做对了,您高估了并行执行的效率。您没有提供有关您正在使用的体系结构(CPU、内存等)的详细信息,也没有提供代码......但简单地说,我认为超过 4.8 倍的速度增加会达到内存带宽限制,所以内存速度是你的瓶颈。
为什么?
如您所说,光线追踪并不难 运行 并行并且您做对了,所以如果 CPU 不是 100% 忙,我猜您的内存控制器是. 假设您正在追踪 RAM 中的模型(三角形?体素?),您的光线需要在检查命中时读取模型的位。您应该检查您的最大 RAM 带宽,然后将其除以 12(线程),然后将其除以每秒的射线数...发现即使 40 GB/s 也是 "not so much" 当您跟踪很多时射线。这就是为什么 GPU 是光线追踪的更好选择。
长话短说,我建议您尝试分析内存使用情况。