打包/解压缩到int

时间:2012-08-31 17:23:04

标签: c++ c cuda bit-manipulation c++-amp

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

函数return / arguments必须和我定义的一样。 lohi是从不同的线程(因此是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 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:2)

C ++ AMP中的这些原子操作也有以下限制:

  • 您不应混合原子和普通(非原子)读写。 正常读取可能看不到原子写入的结果 记忆位置。正常写入不应与原子写入混合 到相同的内存位置。如果您的计划不符合 这些标准然后会导致不确定的结果。
  • 原子 操作并不意味着任何形式的记忆围栏。原子操作 可以重新安排。这与互锁的行为不同 C ++中的操作。

看起来你违反了第一个。

答案 2 :(得分:1)

看起来过于复杂,而且那里有奇怪的操作。

通常,你只需这样做:

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);
}

请注意,我使用具有显式位大小的类型来说明正在发生的事情。我也冒昧地假设你想要一个“整数”,而不是“无符号整数”。

答案 3 :(得分:0)

试试这个包装:

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

解压缩:

int16_MSB = (int_32 >> 16) & 0xFFFF;
int16_LSB = int_32 & 0xFFFF;