Этот вопрос является расширением этого один. Здесь я представляю два возможных решения и хочу знать их осуществимость. Я использую микроархитектуру Haswell с компиляторами GCC/ICC. Я также предполагаю, что память выровнена.
ВАРИАНТ 1. У меня уже есть выделенная позиция в памяти, и я делаю 3 перемещения памяти. (я использую .memmove
вместо memcpy
, чтобы избежать конструктора копирования)
void swap_memory(void *A, void* B, size_t TO_MOVE){
memmove(aux, B, TO_MOVE);
memmove(B, A, TO_MOVE);
memmove(A, aux, TO_MOVE);
}
ВАРИАНТ 2. Используйте загрузку и сохранение AVX или AVX2, используя преимущества выровненной памяти. К этому решению я считаю, что меняю местами int
типа данных.
void swap_memory(int *A, int* B, int NUM_ELEMS){
int i, STOP_VEC = NUM_ELEMS - NUM_ELEMS%8;
__m256i data_A, data_B;
for (i=0; i<STOP_VEC; i+=8) {
data_A = _mm256_load_si256((__m256i*)&A[i]);
data_B = _mm256_load_si256((__m256i*)&B[i]);
_mm256_store_si256((__m256i*)&A[i], data_B);
_mm256_store_si256((__m256i*)&B[i], data_A);
}
for (; i<NUM_ELEMS; i++) {
std::swap(A[i], B[i]);
}
}
Вариант 2 самый быстрый? Есть ли другая более быстрая реализация, о которой я не упоминаю?
__restrict__
, я бы ожидал, что gcc/icc векторизует циклы для вас. Без__restrict__
я не уверен, сколько компиляторов в наши дни добавят тесты для непересекающихся диапазонов, чтобы проверить, безопасно ли переупорядочивать операции или нет. - person   schedule 19.05.2016