【问题标题】:VirtualAlloc in c# to allocate large memoryc#中的VirtualAlloc分配大内存
【发布时间】:2014-05-22 05:46:56
【问题描述】:

我正在尝试调整供应商的 c# 示例代码以与 PCI-Express 设备连接。该代码基本上将一个大缓冲区分配为一个 int 数组,然后通过 fixed 关键字将其固定,然后将其交给硬件以填充数据。

这很好用,但最终失败了,因为 .Net 被限制在数组中约 20 亿个元素。我可以通过使用 Long 和 gcAllowVeryLargeObjects 关键字的数组将限制推到 16 GB,但最终我仍然遇到 .Net 限制。

在非托管代码中,我可以调用 VirtualAlloc 并直接请求 40 或 50GB,但我不清楚这在 c# 中是否可行,而且我找不到任何好的示例代码。我意识到我可以用不同的语言来做这件事,但至少在 Windows 上我更熟悉.Net,除了程序的这个相对较小的部分之外,几乎没有特定于硬件的代码,所以我想尝试并坚持我所拥有的。

【问题讨论】:

  • “~20 亿”?在 64 位环境中,您可以创建大于 2 GB 的数组,甚至索引也不限于 Int32(请参阅 Array.CreateInstance)。
  • 您的具体问题是什么?你也可以在 C# 中使用VirtualAlloc
  • 即使在 64 位 CLR 应用程序中,每个对象也有 2GB 的硬限制!所以他想要的托管代码是不可能的。

标签: c# memory virtualalloc


【解决方案1】:

您可以调用 VirtualAlloc。签名是

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType lAllocationType, MemoryProtection flProtect);

您可以在 pinvoke.net 上找到大多数 pinvoke 结构和签名:VirtualAlloc

或者,看看AllocHGlobal func

【讨论】:

    【解决方案2】:

    gcAllowVeryLargeObjects 应该可以正常工作,你确定不行吗?您可能必须将目标 CPU 显式设置为仅 x64。

    在任何情况下,您都可以使用 hack struct 来获得较大的值类型(您可以将其用作数组):

    unsafe struct Test
    {
      public fixed byte Data[1024];
    }
    
    unsafe void Main()
    {
        Test[] test = new Test[16 * 1024 * 1024];
    
        // We've got 16 * 1024 * 1024 * 1024 here.
        fixed (Test* pTest = test)
        {
    
        }
    }
    

    这确实有它的限制(不安全的结构有一个最大大小),但它应该能让你到达你需要的地方。

    但是,最好通过 P/Invoke 简单地调用 VirtualAlloc。或者更好的是,使用Marshal.AllocHGlobal,它确实应该做同样的事情(虽然你不能指定任何参数,除了大小)。

    【讨论】:

    • 谢谢,这看起来是一个非常简单的解决方案。我没有想到尝试一个结构数组。我还将研究上面的 pinvoke 方法,因为它可能是一种不那么 hackish 的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    • 2012-02-11
    • 2015-05-02
    • 2011-08-30
    • 2019-02-03
    • 2017-05-24
    相关资源
    最近更新 更多