4

我有一个短裤数组,我想在其中获取一半的值并将它们放入一个大小为一半的新数组中。我想以这种模式获取特定值,其中每个块是 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]. 但是,我不知道如何将事物“压缩”在一起并删除白色值。看来如果我能做到这一点,我就根本不需要面具了。

怎么可能呢?

无论如何,最终我也想做与此操作相反的操作,并创建一个两倍大小的新数组并在其中展开当前值。

我还将在白色块中插入新值,我必须用原始数据中的每对短裤迭代地计算这些值。这种计算不能向量化,但结果值的插入应该是向量化的。如何将当前值“展开”到新数组中,插入计算值的最佳方法是什么?我是否应该为每个 128 位迭代计算它们并将它们放入自己的临时块(64 位?128 位?),然后做一些事情来批量插入?还是应该将它们直接放置到我的目标__m128i中,因为它的成本似乎应该等同于放入临时设备?如果是这样,如何在不弄乱我的其他价值观的情况下做到这一点?

我宁愿为此最多使用 SSE2 操作。

4

1 回答 1

1

这是您可以尝试的大纲:

  • 使用带有零的寄存器的交错指令 ( _mm_unpackhi/lo_epi16) 来“展开”您的 16 位值。现在您将拥有两个看起来像B_R_B_R_.
  • 右移创建_B_R_B_R
  • 并且 R 不在第一个版本中B___B___
  • 并且 B 不在第二个版本中___R___R
  • 或一起B__RB__R

在另一个方向上,在使用 shift/and/or 设置后最后使用 _mm_packs_epi32。

每个方向应该是 10 个 SSE 指令(不包括常量设置、零和 AND 掩码以及加载/存储)。

于 2013-01-07T19:20:35.700 回答