AVX2, Wie kann man effizient vier Ganzzahlen in gerade Indizes eines 256-Bit-Registers laden und in ungerade Indizes kopieren?

Ich habe ein ausgerichtetes Array von Ganzzahlen im Speicher, das die Indizes I0, I1, I2, I3 enthält. Mein Ziel ist es, sie in ein __m256i-Register zu bringen, das I0, I0 + 1, I1, I1 + 1, I2, I2 + 1, I3, I3 + 1 enthält. Der schwierige Teil besteht darin, sie als I0, I0 in das 256-Bit-Register zu bringen , I1, I1, I2, I2, I3, I3, danach kann ich einfach ein Register hinzufügen, das 0, 1, 0, 1, 0, 1, 0, 1 enthält.

Ich habe die intrinsische Funktion _mm256_castsi128_si256 gefunden, mit der ich die 4 Ganzzahlen in die unteren 128 Bits des 256-Bit-Registers laden kann, aber ich habe Mühe, die besten intrinsischen Funktionen zu finden, die ich von dort aus verwenden kann.

Jede Hilfe wäre dankbar. Ich habe Zugriff auf alle SSE-Versionen, AVX und AVX2 und möchte dies nur mit Intrinsics tun.

Bearbeiten

Ich denke, das funktioniert, aber ich bin nicht so effizient ... beim Testen.

// _mm128_load_si128: Loads 4 integer values into a temporary 128bit register.
// _mm256_broadcastsi128_si256: Copies 4 integer values in the 128 bit register to the low and high 128 bits of the 256 bit register.
__m256i tmpStuff = _mm256_broadcastsi128_si256 ((_mm_load_si128((__m128i*) indicesArray)));

// _mm256_unpacklo_epi32: Interleaves the integer values of source0 and source1.
__m256i indices = _mm256_unpacklo_epi32(tmpStuff, tmpStuff);

__m256i regToAdd = _mm256_set_epi32 (0, 1, 0, 1, 0, 1, 0, 1);
indices = _mm256_add_epi32(indices, regToAdd);

Edit2: Der obige Code funktioniert nicht, da _mm256_unpacklo_epi32 sich nicht so verhält, wie ich es mir vorgestellt habe. Der obige Code führt zu I0, I0 + 1, I1, I1 + 1, I0, I0 + 1, I1, I1 + 1.

Edit3: Der folgende Code funktioniert, obwohl ich nicht sicher bin, ob er am effizientesten ist:

__m256i tmpStuff = _mm256_castsi128_si256(_mm_loadu_si128((__m128i*) indicesArray));
__m256i mask = _mm256_set_epi32 (3, 3, 2, 2, 1, 1, 0, 0);
__m256i indices= _mm256_permutevar8x32_epi32(tmpStuff, mask);
__m256i regToAdd = _mm256_set_epi32 (1, 0, 1, 0, 1, 0, 1, 0); // Set in reverse order.
indices= _mm256_add_epi32(indices, regToAdd);

Antworten auf die Frage(2)

Ihre Antwort auf die Frage