【问题标题】:I have an error "Dll load error" while using Hybridizer in C#在 C# 中使用 Hybridizer 时出现错误“Dll 加载错误”
【发布时间】:2020-01-15 18:32:25
【问题描述】:

我是第一次使用 Hybridizer。我正在使用 Windows 10、Visual Studio 2019、CUDA 10.1 和 Hybridizer 1.3.0“2019 年 9 月 5 日发布”。虽然我已经按照他们的步骤操作,但我一直收到同样的错误:

加载Hello_World_CUDA.dll时DLL加载错误:126

每当我尝试编写任何简单的代码来测试它时:

using System;
using Hybridizer.Runtime.CUDAImports;
public class Hello_World
{
    [EntryPoint]
    public static void Hello()
    {
        Console.Out.Write("Hello from GPU");
    }

    static void Main()
    {
        cuda.DeviceSynchronize();
        HybRunner runner = HybRunner.Cuda().SetDistrib(1, 2);
        runner.Wrap(new Hello_World()).Hello();
    }
}

即使使用他们的示例而没有任何改变。

我该如何解决这个问题?

【问题讨论】:

  • 您是否验证了CUDA项目也已经构建并且解决方案平台是x64?
  • 两者都做了。同样的问题。
  • 您应该在 github 上提交问题,和/或向支持电子邮件报告。
  • 他们似乎已经有这个问题好几个月了。 github.com/altimesh/hybridizer-basic-samples/issues/66
  • 这将有助于获取完整的异常堆栈和完整的输出日志。你能提供这个吗?

标签: c# visual-studio hybridizer


【解决方案1】:

要解决问题,请按照以下三个步骤进行:

  1. 检查文件是否存在并可从当前目录加载
  2. 确保可以使用LoadLibrary 加载dll
  3. 可以使用GetProcAddress 找到验证符号

为了方便您的调查,请在下面找到运行这些断言的代码

using System;
using System.IO;
using System.Runtime.InteropServices;
using Hybridizer.Runtime.CUDAImports;

public class Hello_World
{
    [EntryPoint]
    public static void Hello()
    {
        Console.Out.Write("Hello from GPU");
    }

    [DllImport("kernel32.dll", EntryPoint = "LoadLibraryA", SetLastError = true)]
    static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string name);

    [DllImport("kernel32.dll", EntryPoint = "FormatMessage", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern int FormatMessage(int dwFlags, IntPtr lpSource, int dwMessageId, int dwLanguageId, [MarshalAs(UnmanagedType.LPArray)] char[] data, uint dwSize, IntPtr args);

    [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true, CharSet = CharSet.Ansi)]
    static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string symbol);

    static unsafe string ErrorToString(int er)
    {
        char[] buffer = new char[2048];
        int res = FormatMessage(0x00001000, // FORMAT_MESSAGE_FROM_SYSTEM
                IntPtr.Zero, er,
                0x0409, // US language -- in case of issue, replace with 0
                buffer, 2048, IntPtr.Zero);
        if (res == 0)
            throw new ApplicationException(string.Format("Cannot format message - Error : {0}", res));
        string resstring;
        fixed (char* ptr = &buffer[0])
        {
            resstring = new string(ptr);
        }
        return resstring;
    }

    static void Main()
    {
        // Trouble-shooting

        // print execution directory
        Console.Out.WriteLine("Current directory : {0}", Environment.CurrentDirectory);
        Console.Out.WriteLine("Size of IntPtr = {0}", Marshal.SizeOf(IntPtr.Zero));

        // first, make sure file exists
        string path = @"Troubleshooting_CUDA.dll"; // replace with actual dll name - you can read that on the output of the build
        if (!File.Exists(path))
        {
            Console.Out.WriteLine("Dll could not be found in path, please verify dll is located in the appropriate directory that LoadLibrary may find it");
            Environment.Exit(1);
        }

        // make sure it can be loaded -- open DLL in depends to missing troubleshoot dependencies (may be long to load)
        IntPtr lib = LoadLibrary(path);
        if (lib == IntPtr.Zero)
        {
            int code = Marshal.GetLastWin32Error();
            string er = ErrorToString(code);
            Console.Out.WriteLine("Dll could not be loaded : {0}", er);
            Environment.Exit(2);
        }

        // finally try to get the proc address -- open DLL in depends to see list of symbols (may be long to load)
        IntPtr procAddress = GetProcAddress(lib, "Hello_Worldx46Hello_ExternCWrapper_CUDA");
        if (procAddress == IntPtr.Zero)
        {
            int code = Marshal.GetLastWin32Error();
            string er = ErrorToString(code);
            Console.Out.WriteLine("Could not find symbol in dll : {0}", er);
            Environment.Exit(3);
        }

        cuda.DeviceSynchronize();
        HybRunner runner = HybRunner.Cuda().SetDistrib(1, 2);
        runner.Wrap(new Hello_World()).Hello();
    }
}

如果第一步失败,您可能需要更改 CUDA 卫星项目的输出目录和/或应用程序的执行目录。

如果它在第二步失败,您想验证您在 x64 中执行(IntPtr 的大小应为 8),并且该 dll 加载。 Dependency walker,你可能会发现 here,是一个很好的工具,你想要 x64 版本。 注意:加载可能会很长

如果在第三步失败,用depends查找符号名称,可能你的CUDA卫星项目不是最新的。

【讨论】:

  • 正如我所料,这是第一步。我没有找到这个“Hello_World_CUDA.dll”文件。应该如何生成?
  • 通过构建卫星项目(CUDA)
  • 如何在 C# 中做到这一点?老实说,我不明白。
  • 卫星项目是一个 vcxproj,因此是一个依赖于 CUDA 的 C++ 项目。首先,这是一个不错的入口点docs.microsoft.com/en-us/visualstudio/ide/…
  • 我试图这样做,但它不断给我不同的错误,如“内部错误”“为 SourceFile 在 'D:\Hybridizer\Hello_World_CUDA\hybridizer-generated-sources\hybridizer.wrappers 指定的路径.cu' 不存在”。我想我会放弃 Hybridizer。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2015-06-20
  • 1970-01-01
相关资源
最近更新 更多