【发布时间】:2018-10-29 15:51:22
【问题描述】:
我正在测试 .Net C# System.Numerics.Vector 类用于打包和解包位的功能。
我希望 Vector 按位左移/右移功能,但目前不可用,因此我尝试使用如下算术和逻辑方法模拟移位。这是我看到的:
使用 Vector.Multiply() 和 Vector.BitwiseOr() 打包(模拟的按位 SHIFT LEFT 和 OR)比数组/指针代码稍差*。
*
但是使用 Vector.Divide() 和 Vector.BitwiseAnd() 解包(模拟按位 SHIFT RIGHT 和 AND)比数组/指针代码差得多**。
**50% 的吞吐量下降
注意:
使用单元测试向量(这也在 cmets 中提出)。
测试基础是在 65536 个整数的块中打包和解包 100Mn 到 1Bn 个整数。我为每个块随机生成了 int[]。
我还测试了按位 (& | >>
我将我的原始测试代码(用于非向量比较)更改为不安全/指针例程,以便在打包(一个单词中的多个整数)与解包方面创建更多类似的测试(一个词对许多整数)。这使非向量代码的整体差异(打包和解包之间)降低到
非优化向量:打包速度是解包速度的 2 倍
优化向量:在打包方面产生了 4 倍的改进(与非优化向量相比),在解包方面得到了 2 倍的改进
未优化的数组/指针:解包比打包快约 5%
优化的数组/指针:对打包产生了 3 倍的改进(相对于未优化的数组指针),对解包产生了 2.5 倍的改进。总体而言,优化的数组/指针打包比优化的数组/指针解包快
优化的数组/指针打包比优化的向量包快约 10%
目前的结论:
Vector.Divide() 与普通算术除法相比似乎是一个相对较慢的实现
-
此外,编译器似乎没有将 Vector.Divide() 代码优化到与 Vector.Multiply() 几乎相同的程度(它支持下面关于优化除法的 cmets)
李> 目前,数组/指针处理在打包数据方面比 Vector 类稍快,在解包方面明显更快
System.Numerics 需要 Vector.ShiftLeft() 和 Vector.ShiftRight() 方法
问题(更新);
- 我的结论是否大致正确?还是有其他方面需要检查/考虑?
更多信息:
int numPages = 8192; // up to >15K
int testSize = 65536;
StopWatch swPack = new StopWatch();
StopWatch swUnpack = new StopWatch();
long byteCount = 0;
for (int p = 0; p < numpages; b++)
{
int[] data = GetRandomIntegers(testSize, 14600, 14800);
swPack.Start();
byte[] compressedBytes = pack(data);
swPack.Stop();
swUnpack.Start();
int[] unpackedInts = unpack(compressedBytes);
swUnpack.Stop();
byteCount += (data.Length*4);
}
Console.WriteLine("Packing Throughput (MB/sec): " + byteCount / 1000 / swPack.ElapsedMilliseconds);
Console.WriteLine("Unpacking Throughput (MB/sec): " + byteCount / 1000 / swUnpacking.ElapsedMilliseconds);
【问题讨论】:
-
与左移乘法不同,右移除法仅适用于 无符号 整数。如果您使用有符号整数,则编译器无法安全地使用移位优化除法。
-
@PaulR:你可以,只需要一些额外的指令来处理算术右移与有符号除法之间的舍入差异。请参阅 godbolt.org/g/6HDjhB 以获取来自
v4si div2(v4si v) { return v/2; }的 gcc/clang 输出,其中 v4si 是 32 位int的 GNU C 本机向量。其他除数的代码生成很有趣; 2 的幂仍然很便宜,其他除数给你一个乘法逆元。 -
@PeterCordes:是的,我主要考虑 2 的幂,并直接转换为单个移位指令,但是当然还有进一步的优化来处理其他除数和带符号值的除法等,尽管这些好处并没有那么显着。
-
我确实使用了 Vector
。所以:我仔细检查了我的测试,然后想知道 AND、XOR、>> 和 > 与 的情况下测试了打包和解包,我看到了类似的差异,即解包速度要慢得多。如果我关闭“优化代码”,则打包:解包速度从 4 倍下降到 1.3 倍——这似乎表明 > 与 & 一起优化。这听起来对吗? -
Division 据我所知,没有被 CLR 优化过。在尽可能优化的代码中,这仍然会生成对通用“除以某个向量”方法的函数调用 - 右手操作数是常量将被忽略。
标签: c# vector bitwise-operators simd system.numerics