我最近发现了 C# Vector<T> 类,它使用硬件加速(即 SIMD:单指令多数据)将向量组件作为单指令执行操作。换句话说,它在一定程度上并行化了数组操作。
由于您尝试将整数位掩码扩展为数组,因此您可能正在尝试做类似的事情。
如果您处于unrolling your code 的位置,这将是一个值得强烈考虑的优化。但是,如果您只是很少使用它们,也请权衡一下against the costs。还要考虑内存开销,因为Vectors 真的 想要在连续内存上操作(在 CLR 中称为Span<T>),所以当你从数组中实例化您自己的向量。
以下是如何进行屏蔽的示例:
//given two vectors
Vector<int> data1 = new Vector<int>(new int[] { 1, 0, 1, 0, 1, 0, 1, 0 });
Vector<int> data2 = new Vector<int>(new int[] { 0, 1, 1, 0, 1, 0, 0, 1 });
//get the pairwise-matching elements
Vector<int> mask = Vector.Equals(data1, data2);
//and return values from another new vector for matches
Vector<int> whenMatched = new Vector<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
//and zero otherwise
Vector<int> whenUnmatched = Vector<int>.Zero;
//perform the filtering
Vector<int> result = Vector.ConditionalSelect(mask, whenMatched, whenUnmatched);
//note that only the first half of vector components render in the Debugger (this is a known bug)
string resultStr = string.Join("", result);
//resultStr is <0, 0, 3, 4, 5, 6, 0, 0>
注意the VS Debugger is bugged,只显示向量的前半部分。
所以用一个整数作为掩码,你可以试试:
int maskInt = 0x0F;//00001111 in binary
//convert int mask to a vector (anybody know a better way??)
Vector<int> maskVector = new Vector<int>(Enumerable.Range(0, Vector<int>.Count).Select(i => (maskInt & 1<<i) > 0 ? -1 : 0).ToArray());
请注意,(有符号整数)-1 用于向true 发出信号,它具有全为二进制表示。
正向1 不起作用,如果需要,您可以将(int)-1 转换为uint 以启用二进制文件的每一位(但not by using Enumerable.Cast<>())。
但是,由于我的系统中有 8 个元素的容量(支持 4x64 位块),这仅适用于 int32 最多 2^8 的掩码。 这取决于执行环境,基于硬件能力,所以总是使用Vector<T>.Capacity。
因此,您可以获得双倍容量,将 shorts 作为 ints 和 longs(尚不支持新的 Half 类型,也不支持“Decimal”,它们是对应的 float/double 类型到 @987654344 @和int128):
ushort maskInt = 0b1111010101010101;
Vector<ushort> maskVector = new Vector<ushort>(Enumerable.Range(0, Vector<ushort>.Count).Select(i => (maskInt & 1<<i) > 0 ? -1 : 0).Select(x => (ushort)x).ToArray());
//string maskString = string.Join("", maskVector);//<65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 65535, 65535, 65535>
Vector<ushort> whenMatched = new Vector<ushort>(Enumerable.Range(1, Vector<ushort>.Count).Select(i => (ushort)i).ToArray());//{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
Vector<ushort> whenUnmatched = Vector<ushort>.Zero;
Vector<ushort> result = Vector.ConditionalSelect(maskVector, whenMatched, whenUnmatched);
string resultStr = string.Join("", result);//<1, 0, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 14, 15, 16>
由于整数的工作方式,无论是有符号还是无符号(使用最高有效位来指示+/- 值),您可能也需要考虑这一点,例如将0b1111111111111111 转换为short 之类的值。如果你尝试做一些看起来很愚蠢的事情,编译器通常会阻止你,至少。
short maskInt = unchecked((short)(0b1111111111111111));
请确保不要将int32 的最重要位混淆为 2^31。