Я пытаюсь написать достаточно быстрый код сложения векторов по компонентам. Я работаю с (подписанными, я полагаю) 64-битными целыми числами.
Функция
void addRq (int64_t* a, const int64_t* b, const int32_t dim, const int64_t q) {
for(int i = 0; i < dim; i++) {
a[i] = (a[i]+b[i])%q; // LINE1
}
}
Я компилирую с помощью icc -std=gnu99 -O3
(icc, чтобы позже использовать SVML) на IvyBridge (SSE4.2 и AVX, но не AVX2).
Мой базовый уровень — удаление %q
из LINE1. 100 (повторяющихся) вызовов функций с dim=11221184
занимают 1,6 секунды. ICC автоматически векторизует код для SSE; отличный.
Я действительно хочу сделать модульные дополнения, хотя. С %q
ICC не выполняет автоматическую векторизацию кода и выполняется за 11,8 секунды (!). Даже если не учитывать автовекторизацию для предыдущей попытки, это все равно кажется чрезмерным.
Поскольку у меня нет AVX2, для векторизации с помощью SSE требуется SVML, возможно, поэтому ICC не выполняет автоматическую векторизацию. Во всяком случае, вот моя попытка векторизовать внутренний цикл:
__m128i qs = _mm_set1_epi64x(q);
for(int i = 0; i < dim; i+=2) {
__m128i xs = _mm_load_si128((const __m128i*)(a+i));
__m128i ys = _mm_load_si128((const __m128i*)(b+i));
__m128i zs = _mm_add_epi64(xs,ys);
zs = _mm_rem_epi64(zs,qs);
_mm_store_si128((__m128i*)(a+i),zs);
}
Сборка для основного цикла:
..B3.4: # Preds ..B3.2 ..B3.12
movdqa (%r12,%r15,8), %xmm0 #59.22
movdqa %xmm8, %xmm1 #60.14
paddq (%r14,%r15,8), %xmm0 #59.22
call __svml_i64rem2 #61.9
movdqa %xmm0, (%r12,%r15,8) #61.36
addq $2, %r15 #56.30
cmpq %r13, %r15 #56.24
jl ..B3.4 # Prob 82% #56.24
Таким образом, код векторизуется, как и ожидалось. Я знаю, что могу не получить 2-кратного ускорения из-за SVML, но код выполняется за 12,5 секунд, медленнее, чем без векторизации вообще! Это действительно лучшее, что здесь можно сделать?
q
? - person Paul R   schedule 16.12.2013