Я начинаю с SIMD intrinsics, поэтому я благодарю всех за их терпение заранее. У меня есть приложение, включающее сравнение абсолютных различий беззнаковых байтов (я работаю с изображениями в оттенках серого).Как извлечь байты из структуры SSE2 __m128i?
Я попытался AVX, более современные версии SSE и т.д., но в конце концов решил SSE2 кажется достаточным, и имеет большую поддержку отдельных байтов - пожалуйста, поправьте меня, если я ошибаюсь.
У меня есть два вопроса: во-первых, то, что это правильный путь, чтобы загрузить 128-разрядные регистры? Я думаю, что я должен передать данные нагрузки Intrinsics выровненные кратными 128, но будет ли это работать с 2D-кода массива, как это:
greys = aligned_alloc(16, xres * sizeof(int8_t*));
for (uint32_t x = 0; x < xres; x++)
{
greys[x] = aligned_alloc(16, yres * sizeof(int8_t*));
}
(Код выше предполагает XRES и yres одинаковы, и полномочия двух). Это превращается в линейный, непрерывный блок в памяти? Могу ли я тогда, когда я петлю, просто продолжаю передавать адреса (увеличивая их на 128) на встроенные нагрузки SSE2? Или нужно сделать что-то другое для 2D-массивов, подобных этому?
Мой второй вопрос: как только я выполнил всю свою обработку вектора, как я могу извлечь измененные байты из __m128i
? Просматривая руководство Intel Intrinsics Guide, инструкции, которые преобразуют векторный тип в скалярный, редки. Самое близкое, что я нашел, это int _mm_movemask_epi8 (__m128i a)
, но я не совсем понимаю, как его использовать.
Да, и третий вопрос - я предполагал, _mm_load_si128
только загружает подписанные байты? И я не мог найти какую-либо другую функцию загрузки байтов, поэтому, я думаю, вы просто должны вычесть 128 из каждого и позже зачислить ее позже?
Я знаю, что эти основные вопросы для экспертов SIMD, но я надеюсь, что это один будет полезен для начинающих, как я. И если вы считаете, что мой подход к приложению неправильный, или мне будет лучше с более современными расширениями SIMD, я бы с удовольствием узнал. Я просто хотел бы смиренно предупредить, что я никогда не работал с сборкой, и все эти бит-трюки требуют много объяснений, если это поможет мне.
Тем не менее, я благодарен за любые разъяснения имеющихся.
В случае это имеет значение: Я ориентируюсь на маломощные i7 Skylake архитектуры. Но было бы неплохо, чтобы приложение запускалось на гораздо более старых машинах (следовательно, SSE2).
Вы также можете увидеть, будет ли компилятор сначала проинвестизировать его, а затем, если вам нужно больше, что может сделать компилятор, а затем добавьте его позже. в идеале мы все используем код ванили, а компилятор делает SSE, AXV или независимо от того, что поддерживает компьютер, если это то, что создатели компилятора настроили для оптимизации. – Holmz
@Peter Cordez - К сожалению, теперь я не могу даже вычислить способ загрузки моих байтов в 16-байтовый вектор. Команды загрузки/хранения все, кажется, используют векторы как для результатов, так и для аргументов - включая адреса! Моя интуиция заключалась бы в том, что я предоставляю (как аргумент нагрузки) адрес из моего байтового массива, но это невозможно, потому что для наследования нагрузки требуются векторы в качестве аргументов. И я не могу найти встроенный, который возвращает вектор (адрес) из обычного, скалярного 64-битного адреса! – sacheie
@sacheie: справа, для целых чисел вы должны использовать '_mm_loadu_si128 ((const __m128i *) my_int_pointer)'. Вы бы это выяснили, если бы посмотрели на какие-либо учебники, связанные с тегом wikis. –