使用C#的Vector<T>
,我们如何最有效地向量化查找集合中特定元素的索引的操作?
作为约束,集合将始终为整数基元的Span<T>
,并且最多包含1个匹配元素。
我提出了一个似乎还不错的解决方案,但我很好奇我们能否做得更好。这是方法:
在每个插槽中创建一个仅包含目标元素的Vector<T>
。
在输入集向量和上一步中的向量之间使用Vector.Equals()
可获得一个掩码,该掩码在单个匹配插槽中包含1(如果没有匹配,则仅包含0)。
使用包含从1开始的索引(1、2、3、4,...)的预初始化向量,在该向量和上一步的掩码之间调用Vector.Dot()
。每个索引将乘以0,潜在的匹配索引将乘以1。我们得到的是这些乘法的总和,即0或匹配元素的从1开始的索引。
如果结果为0,则返回-1,不匹配。否则,从结果中减去1,使其从0开始,然后返回。
// One-time initialized vector containing { 1, 2, 3, 4, ... }
Vector<ushort> indexes = MemoryMarshal.Cast<ushort, Vector<ushort>>(Enumerable.Range(1, Vector<ushort>.Count).Select(index => (ushort)index).ToArray())[0];
// The input set and the element to search for
Span<ushort> set = stackalloc ushort[]{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
ushort element = 22;
// Interpret input set as a sequence of vectors (set is assumed to have length power of two for brevity)
var setVectors = MemoryMarshal.Cast<ushort, Vector<ushort>>(set);
// Create a vector that contains the target element in each slot
var elementVector = new Vector<ushort>(element);
// Loop per vector rather than per element
foreach (var vector in setVectors)
{
// Get a mask that has a 1 in the single matching slot, or only 0s
var mask = Vector.Equals(vector, elementVector);
// Get the dot product of the mask and the indexes
// This will multiple each index by 0, or by 1 if it is the matching one, and return their sum, i.e. the matching index or 0
// Note that the indexes are deliberately 1-based, to distinguished from 0 (no match)
var index = Vector.Dot(indexes, mask);
// Either return 0 for no match, or reduce the index by 1 to get the 0-based index
return index == 0 ? -1 : index - 1;
}
参考方案
您希望编译器生成的x86 asm是等值比较(pcmpeqb
),pmovmskb
或movmskps
(矢量到具有1字节或4字节元素的位掩码),然后如果掩码不是-零,对第一个置位(bsf
或tzcnt
)进行位扫描。
这将比整数点积更有效!!
您已经有“等于比较”功能,我想我已经看过其他带有Vector-> bitmap内在函数的C#问答。如果有人要编辑此答案或使用自己的C#发布/汇编到此asm的JIT,请这样做。我不知道C#,我只是在这里x86 SIMD。
Java中的<<或>>>是什么意思? - javaThis question already has answers here: Closed 7 years ago. Possible Duplicate: What does >> and >>> mean in Java?我在一些Java代码中遇到了一些陌生的符号,尽管代码可以正确编译和运行,但对于括号在此代码中的作用却感…
菱形运算符<>是否等于<?> - java我在util.TreeSet类中发现,其中一个构造函数正在使用具有空泛型类型的新TreeMap调用另一个构造函数。 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } new TreeMap<>是什么意思…
将谓词<T>转换为Func <T,bool> - c#我有一个包含成员Predicate的类,希望在Linq表达式中使用该类:using System.Linq; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerable&…
声纳测试用例失败 - java我正在尝试为我的项目之一获得声纳报告。我已经运行mvn clean installRunning blah.blah.BlahTest1 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 sec Running blah.blah.BlahTest2 Tests run…
休眠映射<键,设置<值>> - java我有以下表格:@Entity @Table(name = "events") Event --id --name @Entity @Table(name = "state") State --id --name @Entity @Table(name = "action") Action --id …