我正在使用 Visual Studio 2008,在项目设置中我看到“激活扩展指令集”选项,我可以将其设置为 None、SSE 或 SSE2
那么编译器会尝试将指令一起批处理以利用 SIMD 指令?
在如何优化代码方面是否可以遵循任何规则,以便编译器可以使用这些扩展生成高效的汇编程序?
例如,目前我正在开发光线追踪器。着色器接受一些输入并根据输入计算输出颜色,如下所示:
PixelData data = RayTracer::gatherPixelData(pixel.x, pixel.y);
Color col = shadePixel(data);
例如,编写着色器代码以便在一个指令调用中对 4 个不同的像素进行着色是否有益?像这样的:
PixelData data1 = RayTracer::gatherPixelData(pixel1.x, pixel1.y);
...
shadePixels(data1, data2, data3, data4, &col1out, &col2out, &col3out, &col4out);
同时处理多个数据单元。这对于让编译器使用 SSE 指令有好处吗?
谢谢!
我正在使用 Visual Studio 2008,在项目设置中我看到“激活扩展指令集”选项,我可以将其设置为 None、SSE 或 SSE2
那么编译器会尝试将指令批处理在一起以便使用 SIMD 指令?
不,编译器不会自行使用向量指令。它将使用标量 SSE 指令而不是 x87 指令。
您所描述的称为“自动矢量化”。 Microsoft 编译器不会这样做,Intel 编译器 会这样做。
在 Microsoft 编译器上,您可以使用 intrinsics 执行手动 SSE 优化。
三点观察。
最好的加速不是来自优化,而是来自好的算法。因此,请确保首先正确完成该部分。通常这意味着只为您的特定领域使用正确的库。
一旦你的算法正确,就该测量了。工作中通常存在 80/20 规则。 20% 的代码将占用 80% 的执行时间。但为了找到该部分,您需要一个好的分析器。 英特尔 VTune 可以为您提供每个功能的采样配置文件以及准确指出性能杀手的精美报告。如果您有 AMD CPU,另一个免费的替代方案是 AMD CodeAnalyst。
编译器自动向量化功能并不是灵丹妙药。尽管它会非常努力(尤其是Intel C++),但您经常需要通过以向量形式重写算法来帮助它。通过手工制作一小部分瓶颈代码以使用 SIMD 指令,通常可以获得更好的结果。您可以在 C 代码中使用内在函数或使用内联汇编来完成此操作(请参阅上面的 VJo 链接)。
当然,第 2 部分和第 3 部分形成了一个迭代过程。如果您真的对此很认真,那么英特尔人员有一些关于该主题的好书,例如软件优化指南和处理器参考手册。
编译器并不强大,它也有一些限制。如果可以(并且如果将正确的标志传递给它),它将使用 SSE 指令。查看它做了什么的唯一方法是检查编译器生成的汇编代码。
另一种选择是使用 C SSE/SSE2 指令。对于 Windows,您可以在这里找到它们:
http://msdn.microsoft.com/en-us/library/y0dh78ez%28VS.80%29.aspx