[toc]
简介
simd编程利用cpu的向量化部件,通过在同一时间对数组的多个元素进行同时计算,来加快计算速度。
增速的幅度一般要看cpu的向量化寄存器可以容纳多少个数据元素
例如如果可以同时容纳8个整数,那么通过simd,理想的增速将是原来的8倍
概念性simd算法
transfer
transfer可以理解为y=f(x)的问题
x通过f函数的转换变成了y
是一对一的转换
DR3 simd库的代码如下:
std::vector<FloatType> c(SZ, VecXX::SCALA_TYPE(0.5));
VecXX test(v);
auto squareLambda = [](const auto&& rhs) { return rhs*rhs; };
auto res = transform(squareLambda, test);
reduce
reduce可以理解为z = f(x, y);
两个转一个的问题
例如在计算数组最大值时可以使用reduce来不断的减少可选集合
DR3代码如下:
计算最小值
auto minDbl = [](auto lhs, auto rhs) { return return lhs < rhs ? lhs : rhs; };
auto minRes = reduce(test, minDbl);
select
select可以理解为 z = f(x, y, mask);
通过mask来过滤x和y,并把结果合并成z,返回
simd库的现状
c++ simd库目前有很多
例如
- boost simd
- std::simd
- VCL
- DR3
然而这些库没有被工业界广泛使用,更多是处于萌芽阶段,并不成熟
一般,如果c++要使用simd技术来优化代码
很可能是通过裸用AVX之类的库来实现
SIMD原生API介绍
数据类型
16 bytes | 32 bytes | |
---|---|---|
32-bit float | __m128 | __m256 |
64-bit float | __128d | __m256d |
Int | __128i | __m256i |
API
- mm_loadu_ps : 初始化,加载数据
- _mm_storeu_ps : 写回数据
- _mm_mul_ps : 相乘操作
void mul4_vectorized( float* ptr )
{
__m128 f = _mm_loadu_ps( ptr );
f = _mm_mul_ps( f, f );
_mm_storeu_ps( ptr, f );
}
- _mm_add_ps : 相加操作
- _mm_setzero_ps : 初始0向量
- _mm_xor_si128 : 亦或
- _mm_cmpeq_epi32 : 是否相等
- _mm_min_ss :获取最小值
- _mm_max_sd :获取最大
- _mm_rcp_ps :x分之一
- _mm_rsqrt_ps : x根号分之一
- _mm_hadd_ps : [a, b, c, d] and [e, f, g, h] => [a+b, c+d, e+f, g+h]
- _mm_addsub_ps : [a, b, c, d] and [e, f, g, h] => [a-e, b+f, c-g, d+h]
- _mm_round_ps
- _mm_ceil_ps
shuffle:
- _mm_movehl_ps
z = f(x, y);
- _mm_movelh_ps
z = f(x, y);
- _mm_unpacklo_ps
z = f(x, y);
- _mm_unpackhi_ps
z = f(x, y);
- _mm_movehdup_ps
z = f(x);
- _mm_moveldup_ps
z = f(x);
- _mm_broadcastss_ps
z = f(x)
- _mm_shuffle_ps
z = f(x, y, mask)
各取两个
- _mm_blend_ps
z = f(x, y, mask)
- _mm_insert_ps
z = f(x, y, mask)
- _mm_permute_ps
网友评论