【[QRNN搭建][pynvrtc库] 记录解决“OSError: [WinError 126] 找不到指定的模块”问题】

导航:如果你同在搭建QRNN时遇到问题,不妨从问题1按顺序阅读
   如果搭建其他项目中遇到[WinError 126]问题,可尝试直接跳转问题2,希望能带去一些启发。


  最近在做时间序列处理,需要用到Quasi-Recurrent Neural Networks(QRNN),源码地址。但遇到了各种各样的问题,其中最主要的是标题中的问题[WinError 126]
  鉴于当前论坛中关于[WinError 126]的相关问题较少且回答较为单一,写下了第一篇博客。
 

问题1:非静态方法的forward不再支持

  先前配置:torch==1.8.1cuda==11.1。直接运行,往往会出现以下错误:

RuntimeError: Legacy autograd function with non-static forward method is deprecated. Please use new-style autograd function with static forward method.

  原因:pytorch版本高于1.3会出现该问题。当前版本要求forward过程是静态的,所以需要将原代码进行修改。解决方法有两个:
一、修改代码(推荐)
  简单的自定义Function函数较为简单(例如常见的梯度反转,仅包含forward和backward两个函数),网上的例子也有很多。但QRNN源码中的forget_mult.py下,类GPUForgetMult中包含了自定义的编译函数compiler(self)。对于我这种没有系统学过类的人,改变量近乎不可能,调了多半天还是报错,放弃了。(其实后来发现,根本原因还是[WinError 126],其实改成功了hh)
二、torch降级
  其实根本没有“降级”一说,就是将高版本torch卸掉再装。由于高版本的cuda又和低版本的torch不匹配,加之各种冲突报错,后来干脆重新搭了个新环境。所以,如果你对python的“类”比较熟悉,同时也在用QRNN源码,建议按照“Legacy autograd function”的官方指引,将forward修改为静态的即可,不建议为了跑一个QRNN,把原环境都推倒重建。
  重新搭建了环境,当前配置为:torch==1.4.0cuda==10.1,同时安装所需的cupypynvrtc库。

  然后,就来到了标题中的问题:
 

问题2:[WinError 126] 找不到指定的模块

File "C:/XXX/pytorch-qrnn-master/torchqrnn/forget_mult.py", line 199, in <module>
    resulta = ForgetMult()(forget, a, last_h, use_cuda=True)
  File "D:\Anaconda3\envs\XXX\lib\site-packages\torch\nn\modules\module.py", line 532, in __call__
    result = self.forward(*input, **kwargs)
  File "C:/XXX/pytorch-qrnn-master/torchqrnn/forget_mult.py", line 178, in forward
    return GPUForgetMult()(f, x, hidden_init) if use_cuda else CPUForgetMult()(f, x, hidden_init)
  File "C:/XXX/pytorch-qrnn-master/torchqrnn/forget_mult.py", line 119, in forward
    self.compile()
  File "C:/XXX/pytorch-qrnn-master/torchqrnn/forget_mult.py", line 101, in compile
    program = Program(kernel, 'recurrent_forget_mult.cu')
  File "D:\Anaconda3\envs\XXX\lib\site-packages\pynvrtc\compiler.py", line 49, in __init__
    self._interface = NVRTCInterface(lib_name)
  File "D:\Anaconda3\envs\XXX\lib\site-packages\pynvrtc\interface.py", line 87, in __init__
    self._load_nvrtc_lib(lib_path)
  File "D:\Anaconda3\envs\XXX\lib\site-packages\pynvrtc\interface.py", line 110, in _load_nvrtc_lib
    self._lib = cdll.LoadLibrary(name)
  File "D:\Anaconda3\envs\XXX\lib\ctypes\__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "D:\Anaconda3\envs\XXX\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] 找不到指定的模块。

  “Win”的模块是指.dll文件,即找不到某个.dll文件。但请注意:这个“找不到”分两种情况:1. 真的没有该.dll文件  2. 存在该.dll文件,但没有被正确找到。
  一开始以为是情况1(即真的缺某个文件),但又论坛中类似的帖子不一样,报错没有告诉你具体缺哪个.dll,于是各种盲目重装C++运行库,还是于事无补。
  注意到报错中可能和pynvrtc库有关,就去github上的pynvrtc-issue中挨个找相关问题,终于先后找到了两个有联系的回答:回答1回答2
  结论:层层寻找,在pynvrtc库中interface.py文件下的NVRTCInterface类中,将第96行附近的:

            if system() == 'Windows':
                def_lib_name = 'nvrtc64_92.dll'

修改为:对应你的cuda版本号,我是10.1,所以是_101_0)

            if system() == 'Windows':
                def_lib_name = 'nvrtc64_101_0.dll'  # 对应你的cuda版本号

  同时,需检查你的环境目录X:\XXX\Anaconda3\envs\环境名\Library\bin中有该nvrtc64_101_0.dll文件,名称需与以上代码块中刚刚修改的语句完全一致。如果没有,自行百度下载对应cuda版本的nvrtc64.dll文件即可。
  至此,最大的问题终于解决了。距离运行forget_mult.py就只剩下一些小问题,简单列出一个:
 

问题3: ‘bytes’ object has no attribute ‘encode’

  此时若直接运行forget_mult.py,大概率会出现如下错误:

AttributeError: 'bytes' object has no attribute 'encode'

AttributeError: 'Program' object has no attribute '_program'

  溯源具体报错,推测出现了重复编码(.encode())的问题。定位GPUForgetMult类下的compile(self)函数(方法),将103行附近的:

program = Program(kernel.encode(), 'recurrent_forget_mult.cu'.encode())

两个变量的.encode()后缀删去,即改为:

 program = Program(kernel, 'recurrent_forget_mult.cu')

即可解决。
  剩下便是些小细节,例如输出维度等等,便不再一一列举。
 

总结

  当出现”[WinError 126] 找不到指定的模块“的错误时,基本可以断定和.dll文件有关。具体可能有两种情况
  1. 指定位置中确实没有该.dll文件。
  2. 该.dll文件存在,但没有被正确定位和调用(本例)
 
  还有,就是出了问题之后不能只会把报错的最后一行粘贴到百度或者Google上,要静下心来逐行查看出错提示,往往能推断出出错位置,再结合论坛和自身经验完成debug。
  (第一篇blog,希望后面有机会多多记录,帮到更多的人吧)

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值