用 C++ 实现 SIMD
Posted
技术标签:
【中文标题】用 C++ 实现 SIMD【英文标题】:implement SIMD in C++ 【发布时间】:2010-04-29 16:53:11 【问题描述】:我正在编写一些代码,我正在尝试尽可能优化它,基本上让它在一定的时间限制下运行。
下面的调用...
static affinity_partitioner ap;
parallel_for(blocked_range<size_t>(0, T), LoopBody(score), ap);
...下面是执行的内容。
void operator()(const blocked_range<size_t> &r) const
int temp;
int i;
int j;
size_t k;
size_t begin = r.begin();
size_t end = r.end();
for(k = begin; k != end; ++k) // for each trainee
temp = 0;
for(i = 0; i < N; ++i) // for each sample
int trr = trRating[k][i];
int ei = E[i];
for(j = 0; j < ei; ++j) // for each expert
temp += delta(i, trr, exRating[j][i]);
myscore[k] = temp;
我正在使用英特尔的 TBB 来优化它。但我也一直在阅读有关 SIMD 和 SSE2 以及类似性质的内容。所以我的问题是,如何将变量 (i,j,k) 存储在寄存器中,以便 CPU 可以更快地访问它们?我认为答案与实现 SSE2 或它的一些变体有关,但我不知道该怎么做。有什么想法吗?
编辑:这将在 Linux 机器上运行,但我相信使用英特尔的编译器。如果有帮助,我必须在执行任何操作以确保编译器工作之前运行以下命令... source /opt/intel/Compiler/11.1/064/bin/intel64/iccvars_intel64.csh; source /opt/intel/tbb/2.2/bin/intel64/tbbvars.csh ...然后编译我做: icc -ltbb test.cxx -o test
如果没有简单的方法来实现 SSE2,有什么建议可以进一步优化代码吗?
谢谢, 赫里斯托
【问题讨论】:
编译器应该为你做这种事情。 @zdav:C++ 的语义排除了向量化,因为默认情况下指针可能是未对齐的或别名的。 ICC 允许您提供嵌入在代码中的提示,以帮助它更好地进行矢量化。当然,如果您无法控制所提供数据的对齐方式等,那么这将无济于事。 【参考方案1】:您的问题代表了对正在发生的事情的一些困惑。 i,j,k 变量几乎肯定已经保存在寄存器中,假设您正在编译优化(您应该这样做 - 在您的 icc 调用中添加“-O2”)。
您可以使用 asm
块,但考虑到您已经在使用 ICC,更简单的方法是使用 SSE 内在函数。英特尔为他们提供的文档在这里 - http://www.intel.com/software/products/compilers/clin/docs/ug_cpp/comm1019.htm
看起来您可以对***循环进行 SIMD 化处理,但这在很大程度上取决于您的 delta
函数是什么。
【讨论】:
我无法控制 icc 调用。这是一个家庭作业,所以我能做的非常有限。我什至无法编辑完全可以优化的 delta 函数。我会摆弄 asm 块的想法。谢谢。 @Hristo:与 asm 块相比,Intrinsics 应该给您带来更少的麻烦。但是一定要研究自动矢量化。您应该能够找到#pragma
模拟对命令行标志的控制的命令。【参考方案2】:
当您想在 C++ 模块中使用汇编语言时,您可以将其放在 asm
块中,并继续在块外使用您的变量名。您在asm
块中使用的汇编指令将指定正在对哪个寄存器等进行操作,但它们会因平台而异。
【讨论】:
【参考方案3】:如果您使用 GCC,请参阅http://gcc.gnu.org/projects/tree-ssa/vectorization.html,了解如何帮助编译器自动矢量化您的代码和示例。
否则,您需要让我们知道您使用的是什么平台。
【讨论】:
这将在 Linux 机器上运行,但我相信使用英特尔的编译器。如果有帮助,我必须在执行任何操作以确保编译器工作之前运行以下命令... source /opt/intel/Compiler/11.1/064/bin/intel64/iccvars_intel64.csh; source /opt/intel/tbb/2.2/bin/intel64/tbbvars.csh ...然后编译我做:icc -ltbb test.cxx -o test advogato.org/article/871.html 很旧,但看起来很相关。-xW -O2 -vec-report3
。并查看man icc
并搜索vector
。【参考方案4】:
编译器应该为您执行此操作。例如,在 VC++ 中,您可以简单地打开 SSE2。
【讨论】:
SSE2 自动矢量化是 icpc 的默认选项,而 g++ 则是完全正常的选项。从您所展示的内容来看,它可能需要交换内部循环以及允许函数的内联扩展。对于关于显式 simd 的问题更是如此。为什么以上是关于用 C++ 实现 SIMD的主要内容,如果未能解决你的问题,请参考以下文章