Короткий вопрос: если у меня есть функция, которая берет два вектора. Один вход, другой вывод (нет псевдонимов). Я могу выровнять только один из них, какой из них выбрать?
Более длинная версия такова, что рассмотрим функцию,
void func(size_t n, void *in, void *out)
{
__m256i *in256 = reinterpret_cast<__m256i *>(in);
__m256i *out256 = reinterpret_cast<__m256i *>(out);
while (n >= 32) {
__m256i data = _mm256_loadu_si256(in256++);
// process data
_mm256_storeu_si256(out256++, data);
n -= 32;
}
// process the remaining n % 32 bytes;
}
Если in
и out
совпадают с 32 байтами, тогда нет штрафа за использование vmovdqu
вместо vmovdqa
. Наихудший сценарий заключается в том, что оба они не выравниваются, а каждый из четырех загрузок/хранилищ пересекает границу линии кэша.
В этом случае я могу выровнять одну из них с границей строки кэша, обработав несколько элементов сначала, прежде чем входить в цикл. Однако вопрос в том, что выбрать? Между неуравновешенной нагрузкой и хранилищем, какая из них хуже?