Сообщение Re: memcpy используя sse, sse2, avx от 08.03.2016 11:36
Изменено 08.03.2016 11:57 watchmaker
Здравствуйте, Molchalnik, Вы писали:
M>есть блок памяти, выровненный по 32 байта. длина выровнена по 1024 байта. Подскажите, пожалуйста, как не залезая в ассемблер , интринсиками или ещё чем эффективно скопировать этот блок в другой, такого же размера.
Общая идея очень простая:
Впрочем я бы просто удостоверился, что в компиляторе используется достаточно свежая версия memcpy, которая знает про векторные инструкции, и использовал её. Потому как всё равно понадобится какая-то обвязка для такого кода. Например, нужно будет добавить код, который будет решить что делать, если avx процессором не поддерживается. И протестировать насколько вышеприведённый цикл лучше развернуть (может быть 8 итераций), и вообще может быть лучше с конца к началу копировать.
Конечно, memcpy обладает избыточностью и обрабатывает всякие невозможные тут ситуации, но даже с учётом этих затрат эта функция может быть очень хорошим выбором (до тех пор, пока профайлер не покажет, что кроме memcpy оптимизировать уже нечего)
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 итераций), и вообще может быть лучше с конца к началу копировать.
Конечно, memcpy обладает избыточностью и обрабатывает всякие невозможные тут ситуации, но даже с учётом этих затрат эта функция может быть очень хорошим выбором (до тех пор, пока профайлер не покажет, что кроме memcpy оптимизировать уже нечего)
Re: memcpy используя sse, sse2, avx
Здравствуйте, Molchalnik, Вы писали:
M>есть блок памяти, выровненный по 32 байта. длина выровнена по 1024 байта. Подскажите, пожалуйста, как не залезая в ассемблер , интринсиками или ещё чем эффективно скопировать этот блок в другой, такого же размера.
Общая идея очень простая:
Впрочем я бы просто удостоверился, что в компиляторе используется достаточно свежая версия memcpy, которая знает про векторные инструкции, и использовал её. Потому как всё равно понадобится какая-то обвязка для такого кода. Например, нужно будет добавить код, который будет решить что делать, если avx процессором не поддерживается. И протестировать насколько вышеприведённый цикл лучше развернуть (может быть 8 итераций), и вообще может быть лучше с конца к началу копировать. И для очень длинных массивов написать ещё одну версию с non-temporal storage, чтобы кеш заполнять данными, которые всё равно туда не влезут (тут не ясно, бывает ли такой у тебя случай).
Конечно, memcpy обладает избыточностью и обрабатывает всякие невозможные тут ситуации, но даже с учётом этих затрат эта функция может быть очень хорошим выбором (до тех пор, пока профайлер не покажет, что кроме memcpy оптимизировать уже нечего)
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 оптимизировать уже нечего)