前面写过《 Ubuntu14.04下安装Python2.7+Theano0.7+CUDA7.5》,那时Windows下用theano的GPU加速一直失败,今天终于找到了原因,是一个小trick。
1. 环境
在Windows上安装好Visual Studio 2013,CUDA 7.5和python2.7。确保它们都能正常工作。
2. 安装步骤
安装只有一步,安装theano和pycuda包。在命令行中执行:
pip install theano pycuda
如果pip命令不在系统变量中,先切换到pip所在的目录。比如我的机器这样做:
D:
cd "D:\WinPython-64bit-2.7.10.2\python-2.7.10.amd64\Scripts>"
pip install theano pycuda
相关依赖包会自动安装。注意观察安装过程有没有报错,有的话分而治之。我这里是一遍过的。
3. 运行测试
Trick就在这里:Windows上的CUDA编译器nvcc是专门为VS的C++设计的(忘了从哪里看到过这句话,但是应该是事实)。所以用开源编译器与Windows上的nvcc配合是不可行的。明白了这一点测试就容易了。VS专门提供了它的编译环境工具。
在这个目录下可以找到快捷方式打开VS的命令行编译环境:
D:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts\VS2013 x64 本机工具命令提示.lnk
它其实等效于执行了如下命令
%comspec% /k ""D:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"" amd64
其中%comspec%是“C:\Windows\system32\cmd.exe”。
在这个窗口中我们可以正常用nvcc编译程序了,也可以测试GPU加速的theano程序了。测试程序与Ubuntu下相同:
'''
Created on 2015-11-12
@author: tomheaven
'''
# settings
useGPU = True
import os
# 通过环境变量控制theano使用GPU或者CPU
if useGPU:
os.environ["THEANO_FLAGS"] = "device=gpu"
else:
os.environ["THEANO_FLAGS"] = "device=cpu"
from theano import function, config, shared, sandbox
import theano.tensor as T
import numpy
import time
vlen = 10 * 30 * 768 # 10 x #cores x # threads per core
iters = 1000
rng = numpy.random.RandomState(22)
x = shared(numpy.asarray(rng.rand(vlen), config.floatX))
f = function([], T.exp(x))
print(f.maker.fgraph.toposort())
t0 = time.time()
for i in xrange(iters):
r = f()
t1 = time.time()
print("Looping %d times took %f seconds" % (iters, t1 - t0))
print("Result is %s" % (r,))
if numpy.any([isinstance(x.op, T.Elemwise) for x in f.maker.fgraph.toposort()]):
print('Used the cpu')
else:
print('Used the gpu')
在命令行中执行如下命令,运行上述程序(注意修改py文件路径):
D:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\x86_amd64>python E:\文档\程序设计\eclipse_workspace_x64\TestTheano\cn\edu\nudt\tomheaven\testTheano\TestPerformance.py
第一次运行时会theano function会编译一下,运行结果如下:
DEBUG: nvcc STDOUT mod.cu
正在创建库 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/cuda_ndarray/cuda_ndarray.lib 和对象 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/cuda_ndarray/cuda_ndarray.exp
Using gpu device 0: GeForce GTX 870M
DEBUG: nvcc STDOUT mod.cu
正在创建库 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/tmp9x6meo/c8d7bd33dfef61705c2854dd1f0cb7ce.lib 和对象 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/tmp9x6meo/c8d7bd33dfef61705c2854dd1f0cb7ce.exp
DEBUG: nvcc STDOUT mod.cu
正在创建库 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/tmppbq98d/0fc80e98cce631ecaa526b69dd28dae1.lib 和对象 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/tmppbq98d/0fc80e98cce631ecaa526b69dd28dae1.exp
DEBUG: nvcc STDOUT mod.cu
正在创建库 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/tmpovthkp/9f0b0bbbf46218bd545422dbe73ce3fb.lib 和对象 C:/Users/TomHeaven/AppData/Local/Theano/compiledir_Windows-8-6.2.9200-Intel64_Family_6_Model_60_Stepping_3_GenuineIntel-2.7.10-64/tmpovthkp/9f0b0bbbf46218bd545422dbe73ce3fb.exp
[GpuElemwise{exp,no_inplace}(<CudaNdarrayType(float32, vector)>), HostFromGpu(GpuElemwise{exp,no_inplace}.0)]
Looping 1000 times took 0.901000 seconds
Result is [ 1.23178029 1.61879349 1.52278066 ..., 2.20771813 2.29967761
1.62323296]
Used the gpu
程序于0.9秒执行完毕,使用的是GPU。
4. 在IDE中使用Theano
问题已经找到了,但是每次都在命令行中执行程序很麻烦,我们更喜欢Eclipse、pycharm这样的IDE。有一个简单的方法,不更改任何设置,只需在代码最开始添加:
# for windows visual studio
import subprocess
subprocess.Popen('cmd.exe /k "D:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64');
这个其实执行了VS编译环境的初始化过程(注意不要用os.system函数执行,这个函数有BUG)。具体的路径各个机器不一样,请在你的“本机工具命令提示.lnk”中去找。