Re: memcpy используя sse, sse2, avx
От: watchmaker  
Дата: 08.03.16 11:36
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>есть блок памяти, выровненный по 32 байта. длина выровнена по 1024 байта. Подскажите, пожалуйста, как не залезая в ассемблер , интринсиками или ещё чем эффективно скопировать этот блок в другой, такого же размера.

Общая идея очень простая:
#include "emmintrin.h"

void cpy(const char* src, char* dst, size_t sz) {
  using M = __m128i; // __m256 для avx
  const M* s = (const M*)src;
  M* d = (M*)dst;
  for (; sz > 0; sz -= sizeof(M) * 4) {
    *d++ = *s++; 
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
  };
}


Впрочем я бы просто удостоверился, что в компиляторе используется достаточно свежая версия memcpy, которая знает про векторные инструкции, и использовал её. Потому как всё равно понадобится какая-то обвязка для такого кода. Например, нужно будет добавить код, который будет решить что делать, если avx процессором не поддерживается. И протестировать насколько вышеприведённый цикл лучше развернуть (может быть 8 итераций), и вообще может быть лучше с конца к началу копировать. И для очень длинных массивов написать ещё одну версию с non-temporal storage, чтобы кеш заполнять данными, которые всё равно туда не влезут (тут не ясно, бывает ли такой у тебя случай).
Конечно, memcpy обладает избыточностью и обрабатывает всякие невозможные тут ситуации, но даже с учётом этих затрат эта функция может быть очень хорошим выбором (до тех пор, пока профайлер не покажет, что кроме memcpy оптимизировать уже нечего)
Отредактировано 08.03.2016 11:57 watchmaker . Предыдущая версия . Еще …
Отредактировано 08.03.2016 11:48 watchmaker . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.