c# - 用于替换值的内部 SIMD 指令
问题描述
我想知道如何替换字节值Vector128<byte>
我认为可以假设下面的代码resultvector
具有这些值:
<0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0 >
在这里,我想创建一个新向量,其中所有“0”将替换为“2”,所有“1”将替换为“0”,如下所示: <2,2,2,2,0,0,0, 0,2,2,2,2,2,2,2,2>
我不确定这是否有内在函数或如何实现这一目标?
谢谢!
//Create array
byte[] array = new byte[16];
for (int i = 0; i < 4; i++) { array[i] = 0; }
for (int i = 4; i < 8; i++) { array[i] = 1; }
for (int i = 8; i < 16; i++) { array[i] = 0; }
fixed (byte* ptr = array)
{
byte* pointarray = &*((byte*)(ptr + 0));
System.Runtime.Intrinsics.Vector128<byte> resultvector = System.Runtime.Intrinsics.X86.Avx.LoadVector128(&pointarray[0]);
//<0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0>
//resultvector
}
解决方案
指令是pshufb
在现代 .NET 中作为Avx2.Shuffle和Ssse3.Shuffle用于 16 字节版本。在现代 CPU 上,两者都非常快,只有 1 个周期的延迟。
将源数据传递给 shuffle control mask 参数,第一个参数的特殊值是被洗牌的字节,如下所示:
// Create AVX vector with all zeros except the first byte in each 16-byte lane which is 2
static Vector256<byte> makeShufflingVector()
{
Vector128<byte> res = Vector128<byte>.Zero;
res = Sse2.Insert( res.AsInt16(), 2, 0 ).AsByte();
return Vector256.Create( res, res );
}
有关详细信息,请参阅本文_mm_shuffle_epi8
第 18 页的部分。
更新:如果您没有 SSSE3,您可以在 SSE2 中执行相同的操作,使用 2 条指令而不是 1 条指令:
static Vector128<byte> replaceZeros( Vector128<byte> src )
{
src = Sse2.CompareEqual( src, Vector128<byte>.Zero );
return Sse2.And( src, Vector128.Create( (byte)2 ) );
}
顺便说一句,.NET 中存在一个性能问题,它阻止编译器在循环之外加载常量。如果您要在循环中调用该方法并希望最大化性能,请考虑将两个常量向量(0 和 2)作为方法参数传递。
推荐阅读
- html - Why am I getting space stacking v-for list and a regular a tag?
- json - 将 json 数组读入 SQL Server 中的行
- python - Django: Get TabularInline model objects
- android - SQLite query: between
- android - 如何让移动网络浏览器显示这些照片上传选项?
- javascript - 将 KML 文件传递到 Google 地图
- r - 使用R中的flextable和officer包从flextable中删除所有行距
- html - Spinner 在 IE 中不旋转
- python - Python:更改 Python 包的目录以进行开发
- java - 如何在 Hibernate 中使用非主键处理多对多关系?