Понимание SIMD-оптимизации Clang для умножения числа с плавающей точкой на счетчик цикла intC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Понимание SIMD-оптимизации Clang для умножения числа с плавающей точкой на счетчик цикла int

Сообщение Anonymous »

При следующей функции

Код: Выделить всё

void foo(float* result, int size, float y, float delta) {
for (int t = 0; t < size; ++t) {
result[t] = y + delta * t;
}
}
Clang с -O2 генерирует следующую сборку x86-64:

Код: Выделить всё

.LCPI0_0:
.long   0
.long   1
.long   2
.long   3
.LCPI0_1:
.long   4
.long   4
.long   4
.long   4
.LCPI0_2:
.long   65535
.long   65535
.long   65535
.long   65535
.LCPI0_3:
.long   1258291200
.long   1258291200
.long   1258291200
.long   1258291200
.LCPI0_4:
.long   1392508928
.long   1392508928
.long   1392508928
.long   1392508928
.LCPI0_5:
.long   0x53000080
.long   0x53000080
.long   0x53000080
.long   0x53000080
.LCPI0_6:
.long   8
.long   8
.long   8
.long   8
foo(float*, int, float, float):
test    esi, esi
jle     .LBB0_7
mov     eax, esi
cmp     esi, 7
ja      .LBB0_3
xor     ecx, ecx
jmp     .LBB0_6
.LBB0_3:
mov     ecx, eax
and     ecx, 2147483640
movaps  xmm2, xmm1
shufps  xmm2, xmm1, 0
movaps  xmm3, xmm0
shufps  xmm3, xmm0, 0
mov     edx, eax
shr     edx, 3
and     edx, 268435455
shl     rdx, 5
movdqa  xmm4, xmmword ptr [rip + .LCPI0_0]
xor     esi, esi
movdqa  xmm5, xmmword ptr [rip + .LCPI0_1]
movdqa  xmm6, xmmword ptr [rip + .LCPI0_2]
movdqa  xmm7, xmmword ptr [rip + .LCPI0_3]
movdqa  xmm8, xmmword ptr [rip + .LCPI0_4]
movaps  xmm9, xmmword ptr [rip + .LCPI0_5]
movdqa  xmm10, xmmword ptr [rip + .LCPI0_6]
.LBB0_4:
movdqa  xmm11, xmm4
paddd   xmm11, xmm5
movdqa  xmm12, xmm4
pand    xmm12, xmm6
por     xmm12, xmm7
movdqa  xmm13, xmm4
psrld   xmm13, 16
por     xmm13, xmm8
subps   xmm13, xmm9
addps   xmm13, xmm12
movdqa  xmm12, xmm11
pand    xmm12, xmm6
por     xmm12, xmm7
psrld   xmm11, 16
por     xmm11, xmm8
subps   xmm11, xmm9
addps   xmm11, xmm12
mulps   xmm13, xmm2
addps   xmm13, xmm3
mulps   xmm11, xmm2
addps   xmm11, xmm3
movups  xmmword ptr [rdi + rsi], xmm13
movups  xmmword ptr [rdi + rsi + 16], xmm11
paddd   xmm4, xmm10
add     rsi, 32
cmp     rdx, rsi
jne     .LBB0_4
cmp     ecx, eax
je      .LBB0_7
.LBB0_6:
xorps   xmm2, xmm2
cvtsi2ss        xmm2, ecx
mulss   xmm2, xmm1
addss   xmm2, xmm0
movss   dword ptr [rdi + 4*rcx], xmm2
inc     rcx
cmp     rax, rcx
jne     .LBB0_6
.LBB0_7:
ret
Я пытаюсь понять, что здесь происходит. Похоже, что .LBB0_4 — это цикл, который охватывает 8 итераций исходного цикла для каждой итерации (есть 2 инструкции multips, и каждая инструкция охватывает 4 числа с плавающей запятой и rsi) увеличивается на 32). Код в конце, вероятно, предназначен для случая, когда размер не делится на 8. С чем у меня возникают проблемы, так это с остальной частью кода. Что делают все остальные инструкции внутри цикла .LBB0_4 и константы в начале? Есть ли инструмент или аргумент компилятора, который может помочь мне понять результат векторизации SIMD? Может быть, что-то, что превратит это обратно в C++ со встроенными функциями SIMD?
А также, если я изменю код на этот

Код: Выделить всё

void foo(float* result, int size, float y, float delta) {
for (int t = 0; t < size; ++t) {
result[t] = y;
y += delta;
}
}
Clang генерирует гораздо меньше сборок и зацикливает более 16 значений одновременно.
Изменить: я только что понял, что это версия вообще не векторизована и поэтому меньше и, возможно, медленнее.
Каков самый быстрый способ написать этот код?

Подробнее здесь: https://stackoverflow.com/questions/791 ... int-loop-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»