在 c# 中构建一个整数数组,每个调用 c++ 或在 c++ 中构建并传递给 c#?

Posted

技术标签:

【中文标题】在 c# 中构建一个整数数组,每个调用 c++ 或在 c++ 中构建并传递给 c#?【英文标题】:Build an array of ints in c# each calling c++ or build in c++ and pass to c#? 【发布时间】:2012-11-18 00:08:54 【问题描述】:

我用 C++ 编写了一个函数,让我可以通过一个内在函数利用新的英特尔 RdRand 数字随机数生成器。

__declspec(dllexport) int __stdcall GetRdRand32(PUINT32 pValue)

    return _rdrand32_step(pValue);

我已经将它包装起来,以便我可以通过 PInvoke 在 C# 中使用它,它工作正常,如下所示:

[DllImport("CppDynamicLinkLibrary.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int GetRdRand32(out UInt32 str);

我的用例通常可能涉及请求多个随机数,尽管一次可能只有数百个(每个请求者)。我的问题是,无论如何我都在使用 C++,将另一个可以返回随机数的动态数组(或向量)的函数放在一起是否有意义,即与仅对 C++ DLL 进行多次调用相比,这会大大提高性能吗?性能是一个问题,因为这将在一个服务器应用程序上,可能会在类似的时间向许多客户端发送大约 200 个随机数

如果值得做,我会怎么做?我正在考虑以下内容,尽管我的猜测是找到一种将向量导入 C# 的方法很容易成为性能问题?

__declspec(dllexport) void __stdcall vGetRdRand32(std::vector<UINT32> &pArray)

    for (std::vector<UINT32>::iterator It = pArray.begin(); It != pArray.end(); It++ )
        _rdrand32_step(&(*It));

最后,Marshal.Copy 会比后一种方法更好吗,如果可以的话,谁能指出我正确的方向?

【问题讨论】:

您应该测试您的假设,即一种方式比另一种方式更快。 【参考方案1】:

这取决于你需要走多快。为了获得最快的 rdrand 性能,请使用 64 位 rdrands 并使用多个线程进行拉取。 2 线程拉取速度是单线程拉取速度的 2 倍,即使在同一核心上的 2 个超线程上也是如此。

因此,如果您将所有内核上的所有线程设置为 64 位并行拉动,您应该能够接近 800MBytes/s。

这可能与直觉相反,但它源于片上总线上的并行性导致了这种性能特征。

循环中的单个线程在 Ivy Bridge 上可能获得 70MBytes/s。

因此,对于 200 个随机数,调用开销将占主导地位。但是对于几兆字节,如果您希望它尽可能快,则生成线程是值得的。

【讨论】:

【参考方案2】:

当然,从单个调用中获取 200 个随机数将比从 200 个不同调用中获取 200 个随机数更快。它甚至可能快很多倍。但很可能你说的是毫秒的差异。所以可能不值得去做。几毫秒的差异会对您的应用程序的整体性能产生显着影响吗?

如果你决定这样做,你可能不想惹vector,而是想惹UINT32[]。在 C# 和 C++ 之间编组 vector 充其量是困难的。出于所有实际目的,这是不可能的。

有关如何编组数组的示例,请参阅 Marshaling Different Types of Arrays。

您可能希望在 C# 中分配数组并将其与大小一起传递给 C++ 函数。这样,您不必担心释放内存。如果您让 C++ 代码分配并返回数组,那么 C# 代码将不得不调用 C++ 函数来释放内存。

【讨论】:

优秀的答案。对关于性能的稍微开放式的问题表示歉意;这当然需要测试。你所做的事情给了我很大的方向,让我可以比较。

以上是关于在 c# 中构建一个整数数组,每个调用 c++ 或在 c++ 中构建并传递给 c#?的主要内容,如果未能解决你的问题,请参考以下文章

力扣刷题:加一(C++和C#)

力扣刷题:加一(C++和C#)

将 C++ 数组返回到 C#

C# 中锯齿状数组的内存分配与 C++ 中的二维数组内存分配

C#:使用 char** 参数调用 C++ DLL

当 C# 调用 c++ 函数时,是不是可以在被调用的 c++ 函数中初始化数组并返回到 C#?