мне было интересно, если есть/AVX2 целого число инструкции SSE2 или последовательность команд (или встроенные функции) должны быть выполнены для того, чтобы достичь следующего результата:C++ SSE2 или AVX2 встроенные функции для градации серого для преобразования ARGB
Учитывая строка 8 байт пикселей вида:
A = {a, b, c, d, e, f, g, h}
есть ли способ, чтобы загрузить эти пиксели в регистре YMM, который содержит 8 32-битные ARGB пикселей, таким образом, что начальное значение градации серого получает транслируемые к другим 2 байта каждого соответствующий 32-битный пиксель? Результат должен быть что-то вроде этого: (0 является альфа-значение)
B = {0aaa, 0bbb, 0ccc, 0ddd, 0eee, 0fff, 0ggg, 0hhh}
Я полный новичок в векторных расширений, так что я даже не знаю, как подойти к этому, или, если это вообще возможно ,
Любая помощь будет оценена по достоинству. Благодаря!
Update1
Спасибо за ваши ответы. У меня все еще есть проблема:
Я собрал этот небольшой пример и скомпилировал его с VS2015 на x64.
int main()
{
unsigned char* pixels = (unsigned char*)_aligned_malloc(64, 32);
memset(pixels, 0, 64);
for (unsigned char i = 0; i < 8; i++)
pixels[i] = 0xaa + i;
__m128i grayscalePix = _mm_load_si128((const __m128i*)pixels);
__m256i rgba = _mm256_cvtepu8_epi32(grayscalePix);
__m256i mulOperand = _mm256_set1_epi32(0x00010101);
__m256i result = _mm256_mullo_epi32(rgba, mulOperand);
_aligned_free(pixels);
return 0;
}
Проблема заключается в том, что после выполнения
__m256i rgba = mm256_cvtepu8_epi32(grayscalePix)
RGBA имеет только первые четыре двойных набора. Последние четыре равны 0.
Руководство разработчика Intel говорит:
VPMOVZXBD ymm1, xmm2/m64
Нулевой простираться 8 упакованы 8-битные целые числа в низких 8 байт xmm2/m64 до 8 упакованных 32-разрядных целых чисел в ymm1.
Я не уверен, что это предполагаемое поведение, или я все еще что-то пропустил.
Спасибо.
Ваш код выглядит правильно. Вы уверены, что не просто проверяете это неправильно? Или что компилятор не оптимизировал некоторые из них, потому что результаты не используются? [On Godbolt] (https://godbolt.org/g/TR15E9), мне пришлось использовать '-O0', чтобы компилятор сохранял векторные ops. Даже '-Og' или' -O1' оптимизировали все, кроме malloc/free. Попробуйте сохранить вектор в массив 'uint32_t' и напечатать его с помощью' printf' или что-то вроде C++ ish. –
Оптимизатор не вызывает беспокойства, поскольку я тестировал это в режиме отладки, но вы все еще были правы, хотя :) По-видимому, отладчик VS не отображает значения '_m256i' правильно. Похоже, что он обрезает их на границе '_m128i'. Кроме того, окно регистров тоже не помогло. Все выглядит хорошо после того, как я сохранил вектор в памяти и сделал «printf», поэтому, я думаю, спасибо в порядке :) – redeye
О, ничего не значит, все плохо, если вы не можете доверять отладчику! Получается ли лучше с отладчиком, когда вы используете результат? –