提高Bitconverter.ToInt16的性能

Tom*_*Tom 5 c# unsafe-pointers bitconverter

我正在从USB设备收集数据,这些数据必须转到音频输出组件.目前,我没有足够快地提供数据以避免输出信号中的咔嗒声.所以每毫秒都很重要.

目前,我正在收集以65536字节的字节数组传送的数据.前两个字节表示小端格式的16位数据.这两个字节必须放在double数组的第一个元素中.后两个字节必须放在不同双数组的第一个元素中.然后对65536缓冲区中的所有字节重复此操作,以便最终得到2 double[]个大小为16384的数组.

我目前正在使用BitConverter.ToInt16,如代码所示.运行它需要大约0.3ms,但必须完成10次才能将数据包发送到音频输出.所以开销是3ms,这足以使一些数据包最终无法按时交付.

byte[] buffer = new byte[65536];
double[] bufferA = new double[16384];
double[] bufferB = new double[16384]

for(int i= 0; i < 65536; i +=4)
{
    bufferA[i/4] = BitConverter.ToInt16(buffer, i);
    bufferB[i/4] = BitConverter.ToInt16(buffer, i+2);
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能改善这个?是否可以使用不安全的代码复制值?我没有这方面的经验.谢谢

AAA*_*ddd 4

使用指针和 .这使我的发布速度提高了三倍unsafe。也许还有其他微观优化,但是我会将这些细节留给大众

\n\n

更新

\n\n

我原来的算法有一个错误,可以改进

\n\n

修改代码

\n\n
public unsafe (double[], double[]) Test2(byte[] input, int scale)\n{\n   var bufferA = new double[input.Length / 4];\n   var bufferB = new double[input.Length / 4];\n\n   fixed (byte* pSource = input)\n      fixed (double* pBufferA = bufferA, pBufferB = bufferB)\n      {\n         var pLen = pSource + input.Length;\n         double* pA = pBufferA, pB = pBufferB;\n\n         for (var pS = pSource; pS < pLen; pS += 4, pA++, pB++)\n         {\n            *pA = *(short*)pS;\n            *pB = *(short*)(pS + 2);\n         }\n      }\n\n   return (bufferA, bufferB);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

基准测试

\n\n

每个测试运行 1000 次,每次运行前都会收集垃圾,并缩放到不同的数组长度。所有结果均根据原始 OP 版本进行检查

\n\n

测试环境

\n\n
----------------------------------------------------------------------------\nMode             : Release (64Bit)\nTest Framework   : .NET Framework 4.7.1 (CLR 4.0.30319.42000)\n----------------------------------------------------------------------------\nOperating System : Microsoft Windows 10 Pro\nVersion          : 10.0.17134\n----------------------------------------------------------------------------\nCPU Name         : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz\nDescription      : Intel64 Family 6 Model 58 Stepping 9\nCores (Threads)  : 4 (8)      : Architecture  : x64\nClock Speed      : 3901 MHz   : Bus Speed     : 100 MHz\nL2Cache          : 1 MB       : L3Cache       : 8 MB\n----------------------------------------------------------------------------\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果

\n\n
--- Random Set of byte ------------------------------------------------------\n| Value    |    Average |    Fastest |    Cycles | Garbage | Test |    Gain |\n--- Scale 16,384 -------------------------------------------- Time 13.727 ---\n| Unsafe   |  19.487 \xc2\xb5s |  14.029 \xc2\xb5s |  71.479 K | 0.000 B | Pass | 59.02 % |\n| Original |  47.556 \xc2\xb5s |  34.781 \xc2\xb5s | 169.580 K | 0.000 B | Base |  0.00 % |\n--- Scale 32,768 -------------------------------------------- Time 14.809 ---\n| Unsafe   |  40.398 \xc2\xb5s |  31.274 \xc2\xb5s | 145.024 K | 0.000 B | Pass | 56.62 % |\n| Original |  93.127 \xc2\xb5s |  79.501 \xc2\xb5s | 329.320 K | 0.000 B | Base |  0.00 % |\n--- Scale 65,536 -------------------------------------------- Time 18.984 ---\n| Unsafe   |  68.318 \xc2\xb5s |  43.550 \xc2\xb5s | 245.083 K | 0.000 B | Pass | 68.34 % |\n| Original | 215.758 \xc2\xb5s | 160.171 \xc2\xb5s | 758.955 K | 0.000 B | Base |  0.00 % |\n--- Scale 131,072 ------------------------------------------- Time 22.620 ---\n| Unsafe   | 120.764 \xc2\xb5s |  79.208 \xc2\xb5s | 428.626 K | 0.000 B | Pass | 71.24 % |\n| Original | 419.889 \xc2\xb5s | 322.388 \xc2\xb5s |   1.461 M | 0.000 B | Base |  0.00 % |\n-----------------------------------------------------------------------------\n
Run Code Online (Sandbox Code Playgroud)\n