【发布时间】:2017-01-17 19:47:32
【问题描述】:
出于好奇和一些奇怪的行为观察。
在使用 win32 内存管理功能(malloc/new afterall 去那里)为进程本身分配和在集成英特尔上分配纹理时,x86 进程的地址空间是如何呈现的GPU使用机器的共享内存? GPU分配是进程地址空间的一部分吗?因为我今天看到我的流程发生了奇怪的事情。我在 x64 机器上使用 x86 进程,我的进程提交内存大小约为 ~1.3Gb,GPU 共享内存消耗约为 600Mb,当尝试分配 32Mb 缓冲区时,我开始从 HeapAlloc 获取 ENOMEM。我不相信碎片是在这里处理的事情,因为这个过程运行到分钟。所以我得到的印象是GPU内存被计算在进程地址空间中,否则我无法解释HeapAlloc为什么会为CRT堆返回null。旁注,没有 /LARGEADDRESSAWARE 的 DLL 链接,所以 2Gb 看起来是上述数字的总和 (1.3+0.6)
我对吗?错误的?谁能解释一下它是如何工作的?
EDIT001:稍微澄清一下,GPU 消耗约 600Gb 并不是突然的,但因为我使用 DirectX 分配纹理。
EDIT002:添加了测试
我在这里跳过了设备初始化
constexpr size_t dim = 5000;
CD3D11_TEXTURE2D_DESC texDescriptor(DXGI_FORMAT_D24_UNORM_S8_UINT, 暗淡, 暗淡, 1, 1, D3D11_BIND_DEPTH_STENCIL);
std::vector<std::vector<uint8_t>> procData;
std::vector<CComPtr<ID3D11Texture2D>> gpuData;
// Some device/context init here
for(;;)
{
{
CComPtr<ID3D11Texture2D> tex;
hr = device->CreateTexture2D(&texDescriptor, nullptr, &tex);
if(SUCCEEDED(hr))
{
gpuData.emplace_back(tex);
}
else
{
std::cout << "Failed to create " << gpuData.size() << "th texture." << std::endl;
}
}
{
try
{
std::vector<uint8_t> buff(dim * dim, 0);
procData.emplace_back(buff);
}
catch(std::exception& ex)
{
std::cout << "Failed to create " << procData.size() << "th buffer." << std::endl;
}
}
}
提醒一下,它是 x86 进程,没有 LARGEADRESSAWARE 设置,因此,2Gb 可用。 上面的代码产生了 35 个缓冲区和 34 个纹理。如果注释掉纹理创建块,则创建了 70 个缓冲区。嗯……
【问题讨论】:
-
我不是 GPU 专家,但任何指定进程的虚拟内存映射都可以通过 VMMap 轻松可视化。我建议您使用此工具并打印您感兴趣的缓冲区地址,以便您确定它们属于哪个部分。
-
已经做了……乍一看没什么特别的,去图吧
标签: windows visual-c++ memory-management gpu directx-11