У меня есть следующий код, который копирует данные из памяти в буфер DMA:
for (; likely(l > 0); l-=128)
{
__m256i m0 = _mm256_load_si256( (__m256i*) (src) );
__m256i m1 = _mm256_load_si256( (__m256i*) (src+32) );
__m256i m2 = _mm256_load_si256( (__m256i*) (src+64) );
__m256i m3 = _mm256_load_si256( (__m256i*) (src+96) );
_mm256_stream_si256( (__m256i *) (dst), m0 );
_mm256_stream_si256( (__m256i *) (dst+32), m1 );
_mm256_stream_si256( (__m256i *) (dst+64), m2 );
_mm256_stream_si256( (__m256i *) (dst+96), m3 );
src += 128;
dst += 128;
}
Вот как выглядит вывод сборки gcc
:
405280: c5 fd 6f 50 20 vmovdqa 0x20(%rax),%ymm2
405285: c5 fd 6f 48 40 vmovdqa 0x40(%rax),%ymm1
40528a: c5 fd 6f 40 60 vmovdqa 0x60(%rax),%ymm0
40528f: c5 fd 6f 18 vmovdqa (%rax),%ymm3
405293: 48 83 e8 80 sub $0xffffffffffffff80,%rax
405297: c5 fd e7 52 20 vmovntdq %ymm2,0x20(%rdx)
40529c: c5 fd e7 4a 40 vmovntdq %ymm1,0x40(%rdx)
4052a1: c5 fd e7 42 60 vmovntdq %ymm0,0x60(%rdx)
4052a6: c5 fd e7 1a vmovntdq %ymm3,(%rdx)
4052aa: 48 83 ea 80 sub $0xffffffffffffff80,%rdx
4052ae: 48 39 c8 cmp %rcx,%rax
4052b1: 75 cd jne 405280 <sender_body+0x6e0>
Обратите внимание на переупорядочение последних инструкций vmovdqa
и vmovntdq
. С приведенным выше кодом gcc
я могу достичь пропускной способности ~ 10 227 571 пакетов в секунду в моем приложении.
Затем я переупорядочу эти инструкции вручную в hexeditor. Это означает, что теперь цикл выглядит следующим образом:
405280: c5 fd 6f 18 vmovdqa (%rax),%ymm3
405284: c5 fd 6f 50 20 vmovdqa 0x20(%rax),%ymm2
405289: c5 fd 6f 48 40 vmovdqa 0x40(%rax),%ymm1
40528e: c5 fd 6f 40 60 vmovdqa 0x60(%rax),%ymm0
405293: 48 83 e8 80 sub $0xffffffffffffff80,%rax
405297: c5 fd e7 1a vmovntdq %ymm3,(%rdx)
40529b: c5 fd e7 52 20 vmovntdq %ymm2,0x20(%rdx)
4052a0: c5 fd e7 4a 40 vmovntdq %ymm1,0x40(%rdx)
4052a5: c5 fd e7 42 60 vmovntdq %ymm0,0x60(%rdx)
4052aa: 48 83 ea 80 sub $0xffffffffffffff80,%rdx
4052ae: 48 39 c8 cmp %rcx,%rax
4052b1: 75 cd jne 405280 <sender_body+0x6e0>
С правильно заказанными инструкциями я получаю ~ 13 668 313 пакетов в секунду. Таким образом, очевидно, что переупорядочение, введенное gcc
, снижает производительность.
Вы сталкивались с этим? Является ли это известной ошибкой или мне нужно заполнить отчет об ошибке?
Флаги компиляции:
-O3 -pipe -g -msse4.1 -mavx
Моя версия gcc:
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)