0%

Windows7 64bitにPyCUDAとTheanoをインストールしてGPU計算する

前回構築したTDM-GCCとMinGW-w64で64bitのPython2.7環境にPyCUDAとTheanoをインストールしてGPUを使って計算してみます。Installing Theano with GPU on Windows 64-bitの続きを参考にして構築していきます。

NumPyとSciPy

msys.batのショートカットをダブルクリックしてMSYSを起動します。まずMinGW-w64環境にpipをインストールします。

$ wget --no-check-certificate -O-  https://bootstrap.pypa.io/get-pip.py | python

NumPySciPyは、Unofficial Windows Binaries for Python Extension Packagesのパッケージを使います。

NumPynumpy‑1.8.2+mkl‑cp27‑none‑win_amd64.whlをダウンロードしてpip installします。

$ pip install /c/Users/masato/Downloads/numpy-1.8.2+mkl-cp27-none-win_amd64.whl

SciPyscipy-0.15.1-cp27-none-win_amd64.whlをダウンロードします。

$ pip install /c/Users/masato/Downloads/scipy-0.15.1-cp27-none-win_amd64.whl

PyCUDA

CUDA Toolkit 6.5以前Windows 7 64bit版のインストーラーをダウンロードしてインストールしてあります。C/C++のCUDA拡張でプログラムを書くのは大変です。Pythonを使ってコンパイル不要で実行できるのは便利です。PuCUDApycuda-2014.1+cuda6519-cp27-none-win_amd64.whlをダウンロードします。

$ pip install /c/Users/masato/Downloads/pycuda-2014.1+cuda6519-cp27-none-win_amd64.whl

nvccがcl.exeを見つけられない

Error compiling CUDA from Command Promptを参考にして、 c:\mingw\msys\msys.batの最初にVisual StudioのPATHを設定します。

c:\mingw\msys\msys.bat
rem ember value of GOTO: is used to know recursion has happened.

call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\x86_amd64\vcvarsx86_amd64.bat"

if "%1" == "GOTO:" goto %2

UnicodeDecodeErrorがでる

このままpycudaパッケージを使うと実行時にUnicodeDecodeErrorが出てしまします。UnicodeDecodeError: ‘utf8’ codec can’t decode byte #37によると、nvccからUTF-8として有効でない文字が出力されているようです。compiler.pyの250行目辺りに以下のコードを追加します。

c:\Python27\lib\site-packages\pycuda\compiler.py
...
self._check_arch(arch)

if options is not None:
options.extend(["-Xcompiler","/wd 4819"])
else:
options = ["-Xcompiler","/wd 4819"]

cubin = compile(source, nvcc, options, keep, no_extern_c,
arch, code, cache_dir, include_dirs)
...

テスト

こちらのTutorialを参考にしてサンプルコードを用意して実行してみます。

~/pycuda-test.py
import pycuda.gpuarray as gpuarray
import pycuda.driver as cuda
import pycuda.autoinit
import numpy
a_gpu = gpuarray.to_gpu(numpy.random.randn(4,4).astype(numpy.float32))
a_doubled = (2*a_gpu).get()
print a_doubled
print a_gpu

簡単な配列計算の実行ですが、PyCUDAのインストールに成功したようです。

$ python pycuda-test.py
[[-5.03633499 -1.2504214 0.87832445 0.86452949]
[ 0.01358639 0.98460299 2.50277209 3.76451278]
[ 0.14301641 -2.11651611 0.39508429 -0.88320005]
[ 2.66914272 0.87537336 -1.17862082 1.94231701]]
[[-2.5181675 -0.6252107 0.43916222 0.43226475]
[ 0.0067932 0.49230149 1.25138605 1.88225639]
[ 0.07150821 -1.05825806 0.19754215 -0.44160002]
[ 1.33457136 0.43768668 -0.58931041 0.9711585 ]]

Theano

Theanoは最近話題のDeep Learningで使うPythonの数値計算ライブラリです。実行時のC++コード生成と、CUDAでGPU計算もできるのが特徴です。TheanoTheano-0.6.0-py2-none-any.whlをダウンロードします。

$ pip install /c/Users/masato/Downloads/Theano-0.6.0-py2-none-any.whl

MSYSのホームディレクトリにTheanoの環境設定ファイルを作成します。

~/.theanorc
[global]
device = gpu
floatX = float32

inconsistent dll linkage

サンプルコードを実行すると、'round' : dll リンクが一貫していません。というエラーがでます。

$ python theano-test.py
...
c:\python27\include\pymath.h(22) : warning C4273: 'round' : dll リンクが一貫して
いません。
c:\program files\nvidia gpu computing toolkit\cuda\v6.5\include\math_fun
ctions.h(2455) : 'round' の前の定義を確認してください

“inconsistent dll linkage” when using Theano with CUDA 6.5 #2055にissueがありました。リポジトリのcuda_ndarray.cuhはすでに修正済みです。Unofficial Windows Binaries for Python Extension Packagesで配布しているパッケージは未対応なので#include <algorithm>を追加します。

C:\Python27\Lib\site-packages\theano\sandbox\cuda\cuda_ndarray.cuh
#ifndef _CUDA_NDARRAY_H
#define _CUDA_NDARRAY_H

#include <algorithm>

テスト

最初にtheanoパッケージが正常にインストールされているか確認します。

$ pip install nose
$ python -c 'import theano; print theano.config' | less
...

Testing Theano with GPUあるサンプルコードを実行してみます。

~/theano-test.py
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' % iters, t1 - t0, 'seconds'
print 'Result is', 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'

まだ警告がでますが最後にUsed the gpuと表示されるのでGPU計算ができているようです。

$ python theano-test.py
...
c:\python27\include\pymath.h(22) : warning C4273: 'round' : dll リンクが一貫して
いません。
c:\program files\nvidia gpu computing toolkit\cuda\v6.5\include\math_fun
ctions.h(2455) : 'round' の前の定義を確認してください
c:\python27\lib\site-packages\numpy\core\include\numpy\npy_1_7_deprecated_api.h(
12) : Warning Msg: Using deprecated NumPy API, disable it by #defining NPY_NO_DE
PRECATED_API NPY_1_7_API_VERSION
ライブラリ C:/Users/masato/AppData/Local/Theano/compiledir_Windows-7-6.1.7601
-SP1-Intel64_Family_6_Model_58_Stepping_9_GenuineIntel-2.7.0-64/tmptykper/73dc8d
0fb3ff37614826ceae3280f478.lib とオブジェクト C:/Users/masato/AppData/Local/Thea
no/compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_58_Stepping_9_Genuin
eIntel-2.7.0-64/tmptykper/73dc8d0fb3ff37614826ceae3280f478.exp を作成中

[GpuElemwise{exp,no_inplace}(<CudaNdarrayType(float32, vector)>), HostFromGpu(Gp
uElemwise{exp,no_inplace}.0)]
Looping 1000 times took 1.23299980164 seconds
Result is [ 1.23178029 1.61879349 1.52278066 ..., 2.20771813 2.29967761
1.62323296]
Used the gpu