我想使用内在函数比较两个浮点变量。如果比较是真的,做其他事做点什么。我想这样做是一个正常的if..else条件。有没有办法使用内在函数?
//normal code
vector<float> v1, v2;
for(int i = 0; i < v1.size(); ++i)
if(v1[i]<v2[i])
{
//do something
}
else
{
//do something
)
如何使用SSE2或AVX执行此操作?
答案 0 :(得分:1)
使用无分支技术完成SIMD条件操作。您可以使用压缩比较指令来获取全零或全一的元素向量。
e.g。当相应的元素匹配具有以下代码的条件时,您可以有条件地将4添加到累加器中的元素:
__m128i match_counts = _mm_setzero_si128();
for (...) {
__m128 fvec = something;
__m128i condition = _mm_castps_si128( _mm_cmplt_ps(fvec, _mm_setzero_ps()) ); // for elements less than zero
__m128i masked_constant = _mm_and_si128(condition, _mm_set1_epi32(4));
match_counts = _mm_add_epi32(match_counts, masked_constant);
}
显然,只有你能想出一个无分支的方式去做分支的两边,这才有效。混合指令通常可以提供帮助。
如果分支的每一侧都有太多的工作,你可能根本不会获得任何加速,特别是如果你的元素大小是4字节或更大。 (当您在16个独立字节上并行执行16次操作时,SIMD非常强大,在4个32位元素上执行4次操作时效率较低)。
答案 1 :(得分:1)
如果你期望v1[i] < v2[i]
几乎永远不会真实,或者通常长期保持不变(即使整体上可能没有特别的偏见),那么另一种技术也适用于提供&#34;真正的条件&#34; (即不是&#34;两者都做,丢弃一个结果&#34;),当然是一个价格,但你也可以实际跳过工作而不是忽略一些结果。
该技术相当简单,进行比较(矢量化),将比较掩码与_mm_movemask_ps
一起收集,然后你有3个案例:
false
,执行适当的&#34;做某事&#34;现在的代码可能更容易向量化,因为条件消失了。true
,相同。并非所有3个案例总是相关的,通常你会应用这个,因为谓词几乎总是以相同的方式,使得其中一个&#34;全部相同&#34;这种情况非常罕见,你可以把它与#34;混合&#34;。
混在一起这种技术绝对不是很有用。 &#34;混合&#34;案件复杂而缓慢。快速路径必须通用且速度足以值得测试您是否可以接受它。
但是它可能很有用,也许其中一个方面非常缓慢和烦人,而分支的另一面是很好的简单的可矢量化代码,相比之下并没有那么长的时间。例如,对于快速近似的超越函数,慢速方可能需要进行参数约简,或者可能必须在获取点积之前对某些向量进行标准化,或者使矩阵正交化,甚至可能从磁盘获取数据。
或者,也许两方都不是很慢,但是他们从缓存中驱逐了彼此的数据(可能两边都是一个适合缓存的数组的循环,但数组并不适合它们)这样做他们无条件地放慢了他们两个。这可能是一个真实的东西,但我还没有在野外看到它(还)。
或者,也许一方无法无条件地执行,做一些通常具有破坏性的事情,甚至可能是一些IO。例如,如果您正在检查错误情况并记录它们。
答案 2 :(得分:0)
我找到了一个对条件SIMD指令非常有用的文档。 这是我的问题的完美解决方案。 If...else condition
文件:http://saluc.engr.uconn.edu/refs/processors/intel/sse_sse2.pdf