Я бы предложил использовать Vc: переносимые типы C ++ с нулевыми издержками для явного параллельного программирования данных библиотека для simd, я слышал, что она предназначена для включения в стандарт C ++.Его легче писать и легче читать.
Пример:
#include <iostream>
#include <Vc/Vc>
int main() {
using A = Vc::SimdArray<int, 8>;
A arr1 = A::Random();
A arr2 = A::Random();
std::cout << arr1 << '\n';
std::cout << arr2 << '\n';
std::cout << arr1 / arr2 << '\n';
}
Выходы:
<1513634383 -963914658 1763536262 -1285037745 | -695608406 -35372374 1025922083 444041308>
<824703811 1962744590 1568022524 -293901648 | 549806324 248334095 1663905340 641164273>
[1, 0, 1, 4, -1, 0, 0, 0]
Следующая функция
using A = Vc::SimdArray<int, 8>;
__attribute__((noinline)) A f(A a0, A a1) {
return a0 / a1;
}
С g++-8.2 -O3 -march=skylake
переводится в следующую сборку:
f(Vc_1::SimdArray<int, 8ul, Vc_1::Vector<int, Vc_1::VectorAbi::Avx>, 8ul>, Vc_1::SimdArray<int, 8ul, Vc_1::Vector<int, Vc_1::VectorAbi::Avx>, 8ul>):
vcvtdq2pd ymm3, xmm1
vcvtdq2pd ymm2, xmm0
vextracti128 xmm1, ymm1, 0x1
vextracti128 xmm0, ymm0, 0x1
vcvtdq2pd ymm1, xmm1
vdivpd ymm2, ymm2, ymm3
vcvtdq2pd ymm0, xmm0
vdivpd ymm0, ymm0, ymm1
vcvttpd2dq xmm2, ymm2
vcvttpd2dq xmm0, ymm0
vinserti128 ymm0, ymm2, xmm0, 0x1
ret
Обратите внимание, что в наборе команд x86 для целочисленного деления отсутствуют инструкции simd.