I have two vectors v1 and v2 of type T and want to create a function that performs v1 & v2 using SIMD instructions and stores the output in a vector out.
Ideally, what we would have is
first1 = v1.begin();
last1 = v1.end();
first2 = v2.begin();
d_first = out.begin();
while(distance(first1, last1) >= 64 / sizeof(T)) {
*d_first = _mm512_and_epi32(first1, first2);
first1 += 64 / sizeof(T)
first2 += 64 / sizeof(T)
d_first1 += 64 / sizeof(T)
}
auto and_op = [](T a, T b) {return a & b;};
std::transform(first1, last1, first2, d_first, and_op);
The first issue w/ the code above is that it works with 32-bit integers. I'm not sure if it expects these to be aligned, and if it does, then the code wouldn't work if T was something like char or short int.
The second issue is I can't get the vector iterators to cast correctly. _mm512_and_epi32 expects two __m512i variables as input. Whenever I pass a contiguous iterator or an address, the compiler always complains saying there's no conversion from what I pass to "'__m512i' (vector of 8
'long long' values)"
I am able to get it to work by doing
__m512i _a = _mm512_load_epi64(&*first1.base());
__m512i _b = _mm512_load_epi64(&*first2.base());'
__m512i _res = _mm512_and_epi64(_a, _b);
_mm512_store_epi64(&*d_first.base(), _res);
But I'm not sure how costly the load/store operations are or whether or not I can skip them.
What is the proper way to run SIMD instructions on large contiguous arrays? Is there a way to make it work for contiguous arrays of all types, regardless of their alignment?