【问题标题】:AMD Gpu Memory dllAMD Gpu 内存 dll
【发布时间】:2014-07-22 21:26:27
【问题描述】:

我正在编写一个用于 C# 应用程序的 C++ dll。 该dll会检查总GPU内存和GPU内存的使用情况。

现在我已经创建了三个方法。第一个确实初始化了 GLew 和其他 OpeGl 的东西。第二个将读取 GPU 的总内存。最后一个会读取 GPU 使用情况。

初始化和总内存方法确实有效,但最后一个我遇到了一些问题。当我调用方法时它会停止,当我调试它时,我可以在 delete[] ids 上设置断点;线没有任何问题。但它不会在返回可用行上返回任何东西(它没有到达那里)。当我删除 delte[] ids 行时,出现错误: '运行时检查失败 #2 - 围绕变量'nCurAvailMemoryInKB' 的堆栈已损坏。'。读取 GPU 内存的使用情况是否有问题?

__declspec(dllexport) float getAvailableMemory()
{
    int available = -1;

    if (wglGetGPUIDsAMD && wglGetGPUInfoAMD)
    {
        UINT n = wglGetGPUIDsAMD(0, 0);
        UINT *  ids = new UINT[n];
        wglGetGPUIDsAMD(n, ids);

        GLint nCurAvailMemoryInKB = 0;
        glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,
            &nCurAvailMemoryInKB);

        available = nCurAvailMemoryInKB;

        delete[] ids;
    }

    return available;
}

我在 C# 中为 Dll 创建了一个测试调用程序: 类程序 {

[DllImport("AmdLib.dll")]
public static extern bool init();
[DllImport("AmdLib.dll")]
public static extern int getTotalMemory();
[DllImport("AmdLib.dll")]
public static extern float getAvailableMemory();

static void Main(string[] args) {
  init();
  Console.WriteLine("Total");
  Console.WriteLine(getTotalMemory());
  Console.WriteLine("Available");
  Console.WriteLine(getAvailableMemory());
}

}

完整的 C++ DLL 源代码如下所示:

#include <stdio.h>
#include <windows.h>
#include <GL/glew.h>
#include <GL/wglew.h>
#include <assert.h>
#include <vector>
#include <string>

using namespace std;

extern "C"
{
    static HGLRC ctx = NULL;

    __declspec(dllexport) bool init()
    {
        HWND hwnd = NULL;

        HINSTANCE hinstance = (HINSTANCE)GetModuleHandle(NULL);

        WNDCLASSA window_class;
        window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
        window_class.lpfnWndProc = DefWindowProc;
        window_class.cbClsExtra = 0;
        window_class.cbWndExtra = 0;
        window_class.hInstance = hinstance;
        window_class.hIcon = NULL;
        window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
        window_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        window_class.lpszMenuName = NULL;
        window_class.lpszClassName = "test_class";

        ATOM atom = RegisterClassA(&window_class);
        hwnd = CreateWindowA("test_class", "htest", WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 1, 1, 1, 1, NULL, NULL, hinstance, NULL);

        if (hwnd == NULL) {
            DWORD err = GetLastError();
            return false;
        }

        HDC hDC = GetDC(hwnd);

        if (hDC == NULL) {
            return false;
        }

        PIXELFORMATDESCRIPTOR const pfd =
        {
            sizeof(PIXELFORMATDESCRIPTOR),
            1,
            PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA,
            0,
            0, 0, 0, 0, 0, 0,
            0,
            0,
            0,
            0, 0, 0, 0,
            0,
            0,
            0,
            PFD_MAIN_PLANE,
            0,
            0, 0, 0
        };
        int pixel_format = ChoosePixelFormat(hDC, &pfd);
        SetPixelFormat(hDC, pixel_format, &pfd);
        ctx = wglCreateContext(hDC);

        if (ctx) {
            if (!wglMakeCurrent(hDC, ctx)) {
                return false;
            }
        }

        ReleaseDC(hwnd, hDC);

        GLenum glew = glewInit();

        return true;
    }

    static void check_gl_error()
    {
        GLenum error = glGetError();

        assert(error == GL_NO_ERROR);
    }

    __declspec(dllexport) int getTotalMemory()
    {
        if (wglGetGPUIDsAMD && wglGetGPUInfoAMD)
        {
            UINT n = wglGetGPUIDsAMD(0, 0);
            UINT *  ids = new UINT[n];
            UINT    total_mem_mb = 0;
            wglGetGPUIDsAMD(n, ids);

            wglGetGPUInfoAMD(ids[0], WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(UINT), &total_mem_mb);

            delete[] ids;

            return total_mem_mb;
        }

        return -1;
    }

    __declspec(dllexport) float getAvailableMemory()
    {
        int available = -1;

        if (wglGetGPUIDsAMD && wglGetGPUInfoAMD)
        {
            UINT n = wglGetGPUIDsAMD(0, 0);
            UINT *  ids = new UINT[n];
            wglGetGPUIDsAMD(n, ids);

            GLint nCurAvailMemoryInKB = 0;
            glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,
                &nCurAvailMemoryInKB);

            available = nCurAvailMemoryInKB;

            //delete[] ids;
        }

        return available;
    }
}

【问题讨论】:

  • 检查wglGetGPUIDsAMD函数指针是否初始化正确,其类型是否与库函数完全匹配。
  • wglGetGPUIDsAMD 确实正确初始化了指针。当我调试时,我可以看到 nCurAvailMemoryInKB 的正确值。但是当我在 glGetIntegerv 之后立即返回它时,我得到了“围绕变量 'nCurAvailMemoryInKB' 的堆栈已损坏”错误。
  • 你解决了吗?我很想自己做这个……

标签: c# c++ dll gpu amd-processor


【解决方案1】:

由于我没有要测试的 ATI 卡,我猜想第一个 wglGetGPUIDsAMD 调用返回 0,你分配一个长度为 0 的数组(有效),最后您尝试删除它(抛出)。介于两者之间的某个地方,您用数据覆盖了该指针周围的内存(从而破坏了守卫并使 VS 抛出)。

现在看看您实际使用该阵列做什么,或者了解您拥有多少 GPU,您从未真正使用过它们中的任何一个。您可以从字面上删除对wglGetGPUIDsAMD 的调用和数组分配/释放,然后只调用glGetIntegerv

【讨论】:

  • 当我在没有其他代码的情况下调用 glGetIntegerv 时,出现“围绕变量 'nCurAvailMemoryInKB' 的堆栈已损坏”错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
  • 2014-08-28
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
相关资源
最近更新 更多