3

2 つの符号付き 16 ビット整数を 32 ビット整数にパック/アンパックしたいと考えています。しかし、私はそれをうまく機能させていません。

私が間違っているかもしれないことについてのアイデアはありますか?

template <typename T>
int read_s16(T& arr, int idx) restrict(amp)
{
    return static_cast<int>((arr[idx/2] >> ((idx % 2) * 16)) << 16) >> 16;
}

template<typename T>
void write_s16(T& arr, int idx, int val) restrict(amp)
{
    // NOTE: arr is zero initialized
    concurrency::atomic_fetch_or(&arr[idx/2], (static_cast<unsigned int>(val) & 0xFFFF) << ((idx % 2) * 16));
}

関数の戻り値/引数は、私が定義したとおりでなければなりません。loとはhi異なるスレッド (つまり、atomic_or) から書き込まれ、読み取りは単一の 32 ビット値を返す必要があります。

16 ビット整数演算は、ターゲット プラットフォームではサポートされていません。

例:

array<int> ar(1); // Container

write_s16(ar, 0, -16);
write_s16(ar, 1, 5);

assert(read_s16(ar, 0) == -16);
assert(read_s16(ar, 1) == 5);
4

4 に答える 4

3

複雑すぎるようで、そこには奇妙な操作があります。

通常、次のようにします。

int32_t Pack(int16_t a, int16_t b)
{
   return (int32_t)((((uint32_t)a)<<16)+(uint32_t)b);
}

int16_t UnpackA(int32_t x)
{
   return (int16_t)(((uint32_t)x)>>16);
}

int16_t UnpackB(int32_t x)
{
   return (int16_t)(((uint32_t)x)&0xffff);
}

何が起こっているのかを説明するために、明示的なビット サイズを持つ型を使用したことに注意してください。また、「符号なし整数」ではなく「整数」が必要であると仮定する自由を取りました。

于 2012-08-31T19:38:19.903 に答える
2

以下のコードは、MSVC でうまく動作します。ご覧のとおり、原則としてコードと同じです。

問題は、配列の内容をゼロに初期化するのを忘れていることでしょうか? プラットフォームは負の数と unsigned int へのキャストをどのように処理しますか?

template <typename T>
int read_s16(T& arr, int idx)
{
    return static_cast<int>((arr[idx/2] >> ((idx % 2) * 16)) << 16) >> 16;
}

template<typename T>
void write_s16(T& arr, int idx, int val)
{
    // NOTE: arr is zero initialized
    arr[idx/2] |= (static_cast<unsigned int>(val) & 0xFFFF) << ((idx % 2) * 16);
}

int main()
{
    int ar[2] = { 0,0 }; // container

    write_s16<int [2]>(ar, 0, -16);
    write_s16<int [2]>(ar, 1, 5);

    assert(read_s16<int [2]>(ar, 0) == -16);
    assert(read_s16<int [2]>(ar, 1) == 5);

    return 0;
}
于 2012-08-31T19:32:31.387 に答える
2

C++ AMP のこれらのアトミック操作には、次の制限もあります。

  • アトミックな読み書きと通常の (非アトミックな) 読み書きを混在させないでください。通常の読み取りでは、同じメモリ位置へのアトミック書き込みの結果が表示されない場合があります。通常の書き込みと、同じメモリ位置へのアトミック書き込みを混在させないでください。プログラムがこれらの基準に準拠していない場合、未定義の結果が発生します。
  • アトミック操作は、いかなる種類のメモリ フェンスも意味しません。アトミック操作は並べ替えられる場合があります。これは、C++ での連動操作の動作とは異なります。

これらの最初のものに違反しているようです。

于 2012-09-04T18:14:46.307 に答える
0

パッキングのためにこれを試してください:

int_32 = (int16_1 & 0x0000FFFF) | (int16_2 & 0xFFFF0000);

開梱の場合:

int16_MSB = (int_32 >> 16) & 0xFFFF;
int16_LSB = int_32 & 0xFFFF;
于 2014-05-29T13:25:58.233 に答える