C++ 向量化条件向量

C++ 向量化条件向量,c++,performance,algorithm,visual-c++,vectorization,C++,Performance,Algorithm,Visual C++,Vectorization,我使用的是一个紧凑的结构,由两条未签名的短裤组成,表示开始和结束位置。 我需要能够快速确定是否存在长度(从开始到结束的差值)超过阈值的范围对象 我将拥有大量的对象,每个对象都有自己的范围数组,因此在列表或其他内容中跟踪哪个范围对象高于阈值是不可行的。这段代码也将经常运行(每一个数组每秒运行很多次),因此它需要高效 struct Range { unsigned short start; unsigned short end; } 我将始终拥有一个大小为2^n的范围数组。虽然我希望在发现超过

我使用的是一个紧凑的结构,由两条未签名的短裤组成,表示开始和结束位置。
我需要能够快速确定是否存在长度(从开始到结束的差值)超过阈值的
范围
对象

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

struct Range
{
 unsigned short start;
 unsigned short end;
}
我将始终拥有一个大小为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;
}
size\u t rangecount=14;
}
毫不奇怪,自动矢量器会给出1202错误,因为我的数据类型不是32或64位宽。我真的不想让我的数据大小增加一倍,并使每个字段都成为无符号整数。所以我猜自动矢量器方法是适合这种情况的


是否有可以处理16位变量的向量指令?如果有,我怎么用C++来对我的循环进行矢量化?< /p> < p>你想知道是否有任何值大于4?< /p> 是的,这有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
\u mm_sub_epi16
与数组结构一起使用,或将
\u mm_hsub_epi16
与数组结构一起使用

实际上,由于
start
首先存储在内存中,因此您将处理
start\u v-end\u v
,因此使用
\u mm\u min\u epi16
-4的向量

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

因此,您最终得到(大约):


是否需要将范围值存储在数组中?为什么不将它们存储在另一个数据结构中,以加快查找速度?因此,在列表或其他内容中跟踪哪些范围对象高于阈值是不可行的。如果您只想确定是否存在违反规则的范围,那么请跟踪该范围。您不必跟踪每个对象即可完成此操作。您多久使用一次
end
?切换到
(开始,大小)
表示而不是
(开始,结束)
是否可行。当然,每次使用时都需要计算
end
,但是如果
end
vs
size
的相对使用率较低,那么最终可能还是一个胜利……我建议给
Range
一个返回大小的成员函数
size()const
(与
begin()相同)常量
end()常量
)。然后,您可以轻松安全地在存储端点的内部表示与存储大小的内部表示之间进行切换,具体取决于使用的频率。对于自动矢量器无法做到的事情,这看起来确实很简单@user173342:处理正好有两个成员的交错数组是一种特殊情况,自动矢量器可能还没有准备好。
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