首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C# Vector<T> SIMD查找匹配元素的索引

用C# Vector<T> SIMD查找匹配元素的索引
EN

Stack Overflow用户
提问于 2019-07-09 14:59:20
回答 2查看 1.3K关注 0票数 6

使用C#的Vector<T>**,如何最有效地向量化查找_的索引_的操作?**

作为约束,集合始终是整数基元的Span<T>,最多包含一个匹配元素。

我想出了一个似乎没问题的解决方案,但我很好奇我们是否能做得更好。以下是一种方法:

  1. 在每个槽中创建一个仅由目标元素组成的Vector<T>
  2. 在上一步的输入集向量和向量之间使用Vector.Equals(),以获得包含单个匹配槽中的1的掩码(如果没有匹配,则只包含0)。
  3. 使用包含基于1的索引(1,2,3,4,.)的预初始化向量,从上一步开始在该向量和掩码之间调用Vector.Dot()。每个索引将被乘以0,除了潜在的匹配指数,它将被乘以1。我们得到的是那些乘法的和,或者是0,或者是匹配元素的基于1的索引。
  4. 如果结果为0,则返回-1表示不匹配。否则,从结果中减去一个,使其基于0,并返回该结果。 //一次初始化向量,包含{ 1,2,3,4,…}向量索引= MemoryMarshal.Cast(Enumerable.Range(1,Vector.Count).Select(索引=> ( ushort )索引).ToArray();//搜索Span set = stackalloc ushort[]{ 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 };ushort元素= 22;//解释输入集为向量序列(假定输入集的长度幂为2表示简洁) var setVectors = MemoryMarshal.Cast (set );//创建一个向量,其中包含每个时隙中的目标元素,elementVector =新的向量(元素);//循环每个向量,而不是每个元素前缀(setVectors中的var向量){ // Get一个掩码,该掩码在单个匹配时隙中有一个1,或者仅包含0svar掩码=Vector.Equals(向量,elementVector);//获取掩码和索引的点乘积/这将使每个索引的倍数为0,如果是匹配的,则为1,并返回它们的和,即匹配索引或0 //注意,即有意基于1的索引,以区别于0(无匹配) var索引=Vector.Dot(索引,掩码);//如果不匹配,则返回0,或者将索引减少1,以获得基于0的索引返回索引== 0?-1 : index - 1;}
EN

回答 2

Stack Overflow用户

发布于 2019-12-14 11:01:04

正如我所看到的,简单的Span.IndexOf已经在使用Intrinsics来搜索一个简单的值。您甚至不需要转换为char来使用它,因为MemoryExtensions.IndexOf只关心大小和Unsafe.SizeOf<ushort>() == sizeof(char)

同样在JsonReaderHelper.IndexOfOrLessThan中,您将找到一个更复杂的向量化搜索示例。它使用字节搜索,但我相信,如果Span<ushort>.IndexOf不合适,您可以根据需要对其进行调整。

票数 3
EN

Stack Overflow用户

发布于 2019-07-09 15:12:52

您希望编译器生成的x86 pcmpeqbpmovmskbmovmskps (具有1字节或4字节元素的向量到位掩码),然后如果掩码为非零,则对第一集位(bsftzcnt)进行位扫描。

那将比整数点积更有效!

您已经有了相等的比较,我想我已经看到了其他的C# Q&比如一个内建的向量->位图。如果有人想编辑这个答案,或者用编译/JIT的C#发布自己的答案,请这样做。我不知道C#,我只是来参加x86 SIMD的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56955433

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档