3

我想将两个带符号的 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));
}

函数返回/参数必须是我定义的。loand是从不同的线程写入的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 回答