【问题标题】:Mono C#/C++ Interop, optimizing matrix multiplications - minimal gain due to overhead?Mono C#/C++ 互操作,优化矩阵乘法 - 由于开销而获得的最小增益?
【发布时间】:2017-11-08 08:09:11
【问题描述】:

我在 C# 上有一个矩阵结构,它在不使用 SSE 内在函数的情况下实现了乘法运算。由于此时我无法访问代码,因此我将尝试尽可能多地指定详细信息,而不是复制/粘贴定义。如果需要,我可以在早上编辑帖子以包含相关定义。

该结构有 16 个floats 定义为M11, M12, M13, ..., M43, M44',指定的顺序布局为:[StructLayout(LayoutKind.Sequential)]

使用属性规范声明 C++ 函数 [DllImport("cppCode.dll", EntryPoint = "MatrixMultiply", CallingConvention = CallingConvention::Cdecl]

我正在尝试使用 P/Invoke 调用 C++ 函数以优化乘法。我的问题是关于传递参数。正如 MSDN 上提到的,如果传递的类型不是 blittable,则成本是 10 到 30 个 CPU + 编组周期。

C# 上的函数调用看起来像

MatrixMultiply(ref matrix1, ref matrix2, out matrix_out);

而 C++ 对应方使用 mat* 接收它们,mat 是具有 4x vec4s 的匹配 C++ 结构。

static extern void MatrixMultiply(mat* m1, mat* m2, mat* out) { *out = *m1 * *m2; }

当分析计算时,增益非常小 - 平均情况下是一微秒或两微秒。然而,最坏的情况变得更糟,从 C# 乘法的 150us 到 C++ 乘法的 400us,这让我认为从导出的 dll 调用函数的开销几乎消除了 SSE 指令的增益。

由于我对 C# 的了解有限,我无法确定发生了什么。难道我做错了什么?在这种特殊情况下,是否有更快的 C#/C++ 通信方法?

【问题讨论】:

  • 您可以使用来自System.Numerics.Vectors 的类型,它们使用 SIMD。甚至还有一个Matrix4x4 类。
  • @cubrr Matarix4x4 class doesn't support SIMD - 我已经检查了反汇编以确保 - 它现在在 Vectors 上。因此,我尝试将 C# 矩阵存储为 4 SIMD:Vec4,并以天真的方式实现了矩阵乘法。还没有时间进行分析(所以我明天肯定会知道它是否更快),但我希望使用与原始实现相同的朴素矩阵乘法获得更好的性能,因为我们将使用 SIMD 寄存器。
  • 嗯,这很令人失望

标签: c# c++ optimization mono pinvoke


【解决方案1】:

如果 Numerics 不能提供足够好的解决方案,最好的办法是尽量减少 p/Invoke 调用。不要为每次乘法调用 Multiply(m1, m2, m_out),而是尽可能在 C++ 端的一次调用中连接矩阵,如下所示:

void MatrixConcat3(m1, m2, m3, m_out);
void MatrixConcat4(m1, m2, m3, m4, m_out);
void MatrixConcat5(m1, m2, m3, m4, m5, m_out);
...

这样可以减少多次调用的开销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-26
    • 2019-01-03
    • 2015-09-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 2019-08-10
    相关资源
    最近更新 更多