【发布时间】:2016-01-04 14:49:42
【问题描述】:
我尝试更改此代码以处理std::vector<int>。
float accumulate(const std::vector<float>& v)
{
// copy the length of v and a pointer to the data onto the local stack
const size_t N = v.size();
const float* p = (N > 0) ? &v.front() : NULL;
__m128 mmSum = _mm_setzero_ps();
size_t i = 0;
// unrolled loop that adds up 4 elements at a time
for(; i < ROUND_DOWN(N, 4); i+=4)
{
mmSum = _mm_add_ps(mmSum, _mm_loadu_ps(p + i));
}
// add up single values until all elements are covered
for(; i < N; i++)
{
mmSum = _mm_add_ss(mmSum, _mm_load_ss(p + i));
}
// add up the four float values from mmSum into a single value and return
mmSum = _mm_hadd_ps(mmSum, mmSum);
mmSum = _mm_hadd_ps(mmSum, mmSum);
return _mm_cvtss_f32(mmSum);
}
参考:http://fastcpp.blogspot.com.au/2011/04/how-to-process-stl-vector-using-sse.html
我将_mm_setzero_ps 更改为_mm_setzero_si128,将_mm_loadu_ps 更改为mm_loadl_epi64,将_mm_add_ps 更改为_mm_add_epi64。
我收到此错误:
error: cannot convert ‘const int*’ to ‘const __m128i* {aka const __vector(2) long long int*}’ for argument ‘1’ to ‘__m128i _mm_loadl_epi64(const __m128i*)’
mmSum = _mm_add_epi64(mmSum, _mm_loadl_epi64(p + i + 0));
我是这个领域的新手。有什么好的资源可以学习这些东西吗?
【问题讨论】:
-
“我是这个领域的新手。有什么好的资源可以学习这些东西吗?” -- 尝试在 StackOverflow 上搜索
[sse]标签 - 有很多很好的问题和答案以及一些有用的代码示例 - 您可能可以从中学到很多东西。 -
您是否有理由需要对 SSE 执行此操作?在这样一个微不足道的操作中,无论有没有 SSE,您都会受到内存带宽的限制。但是对于 SSE,您需要在最后进行水平添加才能获得正确的结果。它更复杂,而且运行速度可能不会更快。更重要的是——除非数字非常小——你不能对大量元素进行前缀求和,因为你会遇到溢出。所以……可读的 C++ 代码同样快,而且……可读。我倾向于将此称为“过早的优化”卓越。
-
@Damon,我认为这太微不足道了,编译器无论如何都会用正确的标志对其进行矢量化。
-
@Zboson:同意,如果对齐允许的话。但它仍然没有任何区别。缓存行中有 16 个整数(4 个 SSE 寄存器)的数据,预取器需要 150-200 个周期才能加载下一个缓存行。因此,除非您做了值得至少一百个周期的事情,否则考虑优化它完全是荒谬的。整个 4 个添加操作(其中 16 个也是如此)几乎不在那个范围内。
-
@Damon,是的,这是我首先对自动矢量化持怀疑态度的一个原因。在大多数情况下,当它工作时,它受内存带宽限制,而在少数情况下,当它不受内存限制时,自动矢量化不会像你想要的那样工作(这就是内在函数有用的原因)。所以最后你需要手工完成。 OP 所做的只是对教育有用。