.NET编组速度 我有一个C++方法签名,看起来像: static extern void ImageProcessing( [MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, [MarshalAs(UnmanagedType.LPArray)]ushort[] outImage, int inYSize, int inXSize);

.NET编组速度 我有一个C++方法签名,看起来像: static extern void ImageProcessing( [MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, [MarshalAs(UnmanagedType.LPArray)]ushort[] outImage, int inYSize, int inXSize);,.net,c++,performance,pinvoke,marshalling,.net,C++,Performance,Pinvoke,Marshalling,我已经用计时方法包装了函数,包括内部和外部。在内部,该函数以0.24秒的速度运行。从外部看,该函数的运行速度为2.8秒,大约慢12倍。发生什么事?编组让我慢了那么多吗?如果是的话,我怎样才能避免呢?我应该使用不安全的代码和指针吗?我有点困惑额外的时间成本是从哪里来的。看看。虽然它的重点是紧凑的框架,但一般原则也适用于桌面。分析部分的相关引用如下: 托管调用不直接调用本机方法。相反,它调用一个JITted存根方法,该方法必须执行一些开销例程,例如确定GC抢占状态的调用(确定GC是否挂起,我们是否需

我已经用计时方法包装了函数,包括内部和外部。在内部,该函数以0.24秒的速度运行。从外部看,该函数的运行速度为2.8秒,大约慢12倍。发生什么事?编组让我慢了那么多吗?如果是的话,我怎样才能避免呢?我应该使用不安全的代码和指针吗?我有点困惑额外的时间成本是从哪里来的。

看看。虽然它的重点是紧凑的框架,但一般原则也适用于桌面。分析部分的相关引用如下:

托管调用不直接调用本机方法。相反,它调用一个JITted存根方法,该方法必须执行一些开销例程,例如确定GC抢占状态的调用(确定GC是否挂起,我们是否需要等待)。也有可能一些编组代码也会被jit到存根中。这一切都需要时间


编辑:同样值得一读的是-同样,CF特定,但仍然相关。还有,尽管这一个可能是特定于CF的(未在桌面上测试)。

您尝试过将两个数组参数切换到IntPtr吗?当编组签名中的所有类型都是可空袭的时,PInvoke是绝对最快的。这意味着Pinvoke只需要一个memcpy来来回获取数据

在我的团队中,我们发现管理PInvoke图层最有效的方法是

  • 保证马歇尔的一切都是可以飞航的
  • 根据需要,通过操纵IntPtr类来手动封送类型(如数组),需要付出代价。这非常简单,因为我们有许多包装器方法/类
    与任何“这将更快”的答案一样,您需要分析这是您自己的代码库。我们是在考虑和分析了几种方法之后才得出这个解决方案的

    不幸的是,答案远比这些建议简单,尽管它们确实有用。基本上,我搞砸了我的计时方式

    我使用的计时代码是:

    Ipp32s timer;
    ippGetCpuFreqMhz(&timer);
    Ipp64u globalStart = ippGetCpuClocks();
    globalStart = ippGetCpuClocks() *2 - globalStart; //use this method to get rid of the overhead of getting clock ticks
    
          //do some stuff
    
    Ipp64u globalEnd = ippGetCpuClocks(); 
    globalEnd = ippGetCpuClocks() *2 - globalEnd;
    std::cout << "total runtime: " << ((Ipp64f)globalEnd - (Ipp64f)globalStart)/((Ipp64f)timer *1000000.0f) << " seconds" << std::endl;
    
    并称之为:

            unsafe {
                fixed (ushort* inImagePtr = theInputImage.DataArray){
                    fixed (ushort* outImagePtr = theResult){
                        ImageProcessing((IntPtr)inImagePtr,//theInputImage.DataArray,
                            (IntPtr)outImagePtr,//theResult,
                            ysize,
                            xsize);
                    }
                }
            }
    

    将可执行时间降至0.3秒(平均运行三次)。对我来说,速度仍然太慢,但速度提高10倍肯定是我老板可以接受的。

    我从中得出的结论是,我需要使用不安全的代码。我不介意,我将进行转换并运行测试,然后让您知道我的结果。
            unsafe {
                fixed (ushort* inImagePtr = theInputImage.DataArray){
                    fixed (ushort* outImagePtr = theResult){
                        ImageProcessing((IntPtr)inImagePtr,//theInputImage.DataArray,
                            (IntPtr)outImagePtr,//theResult,
                            ysize,
                            xsize);
                    }
                }
            }