値の半分を取得し、半分のサイズの新しい配列に入れたいショーツの配列があります。各ブロックが 128 ビット (8 ショート) である、この種のパターンで特定の値を取得したいと考えています。これは私が使用する唯一のパターンです。「一般的なパターン」である必要はありません!
白の値は破棄されます。私の配列サイズは常に 2 の累乗になります。
unsigned short size = 1 << 8;
unsigned short* data = new unsigned short[size];
...
unsigned short* newdata = new unsigned short[size >>= 1];
unsigned int* uintdata = (unsigned int*) data;
unsigned int* uintnewdata = (unsigned int*) newdata;
for (unsigned short uintsize = size >> 1, i = 0; i < uintsize; ++i)
{
uintnewdata[i] = (uintdata[i * 2] & 0xFFFF0000) | (uintdata[(i * 2) + 1] & 0x0000FFFF);
}
私はこのようなものから始めました:
static const __m128i startmask128 = _mm_setr_epi32(0xFFFF0000, 0x00000000, 0xFFFF0000, 0x00000000);
static const __m128i endmask128 = _mm_setr_epi32(0x00000000, 0x0000FFFF, 0x00000000, 0x0000FFFF);
__m128i* data128 = (__m128i*) data;
__m128i* newdata128 = (__m128i*) newdata;
マスクを繰り返し実行_mm_and_si128
して、探している値を取得し、 と組み合わせて_mm_or_si128
、結果を に入れることができますnewdata128[i]
。ただし、物事を「圧縮」して白の値を削除する方法がわかりません。それができれば、仮面はまったくいらない気がする。
どうすればそれができますか?
とにかく、最終的には、この操作の逆も行い、2 倍のサイズの新しい配列を作成し、その中に現在の値を分散させたいと思います。
また、白いブロックに挿入する新しい値もあります。これは、元のデータのショーツの各ペアで繰り返し計算する必要があります。この計算はベクトル化できませんが、結果の値の挿入はベクトル化する必要があります。現在の値を新しい配列に「広げる」にはどうすればよいですか? また、計算された値を挿入する最良の方法は何でしょうか? 128 ビットの反復ごとにすべてを計算し、それらを独自の一時ブロック (64 ビット? 128 ビット?) に入れてから、一括して挿入する必要がありますか? __m128i
それとも、コストは一時的に入れるのと同等であるように思われるので、ターゲットに直接配置する必要がありますか? もしそうなら、私の他の価値観を台無しにすることなく、どうすればそれを行うことができますか?
これにはせいぜいSSE2操作を使用したいと思います。