不安全的c#代码可加快执行速度

不安全的c#代码可加快执行速度,c#,C#,我有一些执行缓慢的代码,我想通过映射到长字符串中的不安全字节指针来加速这些代码 我想加速的代码如下: public ulong seek(ulong ul) { ulong v = table[ul >> 56, ul >> 48 & 0xFF] ^ table2[ul >> 40 & 0xFF ul >> 32 & 0xFF] ^ table[ul >> 24 & 0xFF, ul &g

我有一些执行缓慢的代码,我想通过映射到长字符串中的不安全字节指针来加速这些代码

我想加速的代码如下:

public ulong seek(ulong ul)
{
    ulong v = table[ul >> 56, ul >> 48 & 0xFF] ^ table2[ul >> 40 & 0xFF ul >> 32 &
    0xFF] ^ table[ul >> 24 & 0xFF, ul >> 16 & 0xFF] ^ table2[ul >> 8 & 0xFF, ul &
    0xFF];
    return v;
}
在该代码中,“table”和“table2”分别是256 x 256个表,其中包含随机ulong值。我想通过添加以下内容来修改上述内容:

v2 = /* Add code to compute the same value using unsafe method, byte pointer arithmetic into the ulong "ul" instead of whole bunch of shifting.*/

Console.WriteLine("Called seek, v={0:X16}, v2={1:X16},
                     result={2}",v, v2, v==v2 ? "Pass" : "Fail"
                 );

通过这种方式,我可以测试两种方法是否返回相同的值,通过使用随机值重复调用此函数

如果您处于不安全的上下文中,您确实可以消除位移位:

这两种说法的价值相等:

  var a = (ul >> 48) & 255;
  var b = ((byte*) &ul)[6];
如果你在代码中放一个断点,然后去反汇编,你会看到,尽管第二行看起来很复杂,但它一点也不复杂,你不能更快

var a = (ul >> 48) & 255;
  0000007e  mov         rax,qword ptr [rsp+20h] 
  00000083  sar         rax,30h 
  00000087  and         rax,0FFh 
  0000008d  mov         qword ptr [rsp+28h],rax 
var b = ((byte*) &ul)[6];
  00000092  movzx       eax,byte ptr [rsp+26h] 
  00000097  mov         byte ptr [rsp+30h],al 
其次,索引数组的速度很慢。通常,而不是:

var sum = 0;
for ( var i = 0 ; i < barr.Length ; i++ )
    sum += barr[i];

所有这些通常在处理图像处理时可以看到,在位图中使用.LockBits来获取指向位的指针,以便进行真正快速的处理。

我建议您使用c/c++和DllImport进行此类处理的方法。在调用这些方法之前,不要忘记锁定指针

一些背景:


我广泛从事音频和视频方面的工作。在开发中,首先我创建了一个有效的算法(安全代码、索引到字节[],等等)。然后,我的第一个优化是转移到指针和不安全代码,通过这些,我的速度提高了30%到50%,不再有了。然后,当一切都从算法和体系结构的角度来看,我重新编码成C或C++代码,并使用DLIMPOUNT调用它。在这种情况下,我会留下速度提升指数供您试用,但有时我的速度提升超过10倍。

您确定代码更快吗?在我的机器上,它们在速度上似乎是相同的。下面是我用来测试它的代码:@johnsmith-事实上,这篇文章是不正确的。对数组进行索引并不是很慢。事实上,在这里使用不安全的代码甚至可能带来更多的性能问题,因为每次都必须固定数组,这对GC的性能不利。现在,如果数组位于检查范围内,则为其编制索引的速度可能会较慢。但是,这在默认情况下对于发布模式是禁用的,因此只有在调试模式下才会有性能差异。好吧,我确实在我的机器上(Win7 64+VS64,发布模式)尝试了您的代码,我从不安全代码中获得了两倍的速度。当我把barr换成二维数组,就像OP的情况一样,我发现它的运行速度是普通数组的四倍。但我承认这样一个事实,即它只能在大型阵列上循环时使用,而不仅仅是在OP拥有的函数中使用。相反,整个函数必须是不安全的,并且必须传递一个指针。这很奇怪。即使在发布代码中,它们对我来说运行的速度也是一样的。不确定发生了什么(可能是编译器进行了优化?)我很好奇为什么选择DllImport而不是在C++/CLI中编写它。这会让你两全其美吗?我不喜欢看到c++/CLI——所以这只是个人喜好。所有这些都让我头晕。实际上,我有一个项目(mp3播放器),它是作为遗留代码的CLI包装器编写的——我仍然会使用它来包装类,但对于简单的循环,我想这太过分了。
unsafe
{
    fixed (byte* pb = barr)
    {
        for ( var i = 0 ; i < barr.Length ; i++ )
            sum += pb[i];
    }
}
unsafe
{
    fixed (ulong* ptable = table)
    {
        var pbtable = (byte*)ptable;
        //now you can access table as if it were a byte array
    }
}