矢量化条件涉及短裤

时间:2012-12-21 16:09:57

标签: c++ performance algorithm visual-c++ vectorization

我正在使用2个无符号短裤的紧凑结构,表示开始和结束位置 我需要能够快速确定是否有任何Range个对象的长度(从开始到结束的差异)超过阈值。

我将拥有大量的对象,每个对象都有自己的Range数组,因此在列表或其他内容中跟踪哪些Range对象高于阈值是不可行的。此代码也将经常运行(每个阵列每秒多次),因此它需要高效。

struct Range
{
 unsigned short start;
 unsigned short end;
}

我将永远有一个Range大小为2 ^ n的数组。虽然我想在找到超过阈值的东西时立即中止,但我很确定将它们全部放在一起然后检查结束会更快...假设我可以对循环进行矢量化。虽然如果我能在每个向量的结果块上做一个if语句,那就太棒了。

size_t rangecount = 1 << resolution;
Range* ranges = new Range[rangecount];

...

bool result = false;
for (size_t i = 0; i < ranges; ++i)
{
 result |= (range[i].end - range[i].start) > 4;
}

毫不奇怪,自动矢量化器会产生1202错误,因为我的数据类型不是32位或64位宽。我真的不想将数据大小加倍并使每个字段成为无符号整数。所以我猜测自动矢量化方法已经出来了。

是否有可以处理16位变量的向量指令?如果有,我如何在c ++中使用它们来矢量化我的循环?

1 个答案:

答案 0 :(得分:1)

您想知道是否有任何值大于4?

是的,有SIMD说明。不幸的是,自动矢量化无法处理这种情况。这是一个矢量化算法:

diff_v = end_v - start_v; // _mm_hsub_epi16 
floor_v = max(4_v, diff_v); // _mm_max_epi16 
if (floor_v != 4_v) return true; // wide scalar comparison

使用带有数组结构的_mm_sub_epi16或带有结构数组的_mm_hsub_epi16

实际上,由于start首先存储在内存中,因此您将使用start_v - end_v,因此请使用_mm_min_epi16-4的向量。

每条SSE3指令一次执行8次比较。早期返回仍然是最快的而不是循环。但是,将循环展开多一点可能会为您带来额外的速度(将第一组结果传递给打包的min / max函数以组合它们)。

所以你最终得到(大约):

most_negative = threshold = _mm_set_epi64(0xFCFCFCFCFCFCFCFC); // vectorized -4

loop:
    a = load from range;
    b = load from range;
    diff = _mm_hsub_epi16(a, b);
    most_negative = _mm_min_epi16(most_negative, diff);

    // unroll by repeating the above four instructions 4 times or so
    if (most_negative != threshold) return true;
repeat loop