は、次のPythonコードを考えてみましょう。これを実行解釈
from numpy import float64
from pycuda import compiler, gpuarray
import pycuda.autoinit
# N > 960 is crucial!
N = 961
code = """
__global__ void kern(double *v)
{
double a = v[0]*v[2];
double lmax = fmax(0.0, a), lmin = fmax(0.0, -a);
double smax = sqrt(lmax), smin = sqrt(lmin);
if(smax > 0.2) {
smax = fmin(smax, 0.2)/smax ;
smin = (smin > 0.0) ? fmin(smin, 0.2)/smin : 0.0;
smin = lmin + smin*a;
v[0] = v[0]*smin + smax*lmax;
v[2] = v[2]*smin + smax*lmax;
}
}
"""
kernel_func = compiler.SourceModule(code).get_function("kern")
kernel_func(gpuarray.zeros(3, float64), block=(N,1,1))
ができます:
Traceback (most recent call last):
File "test.py", line 25, in <module>
kernel_func(gpuarray.zeros(3, float64), block=(N,1,1))
File "/usr/lib/python3.5/site-packages/pycuda/driver.py", line 402, in function_call
func._launch_kernel(grid, block, arg_buf, shared, None)
pycuda._driver.LaunchError: cuLaunchKernel failed: too many resources requested for launch
マイセットアップ:pycudaでのPython v3.5.2 == 2016年1月2日Ubuntu 16.04.1(64-bit)、kernel 4.4.0、nvcc V7.5.17ではnumpy == 1.11.1です。グラフィックスカードはNvidia GeForce GTX 480です。
これはマシンで再現できますか?このエラーメッセージの原因は何ですか?
備考:すべてのカーネルがv [0]とv [2]を変更しようとするため、原則として競合状態が存在することがわかりました。しかし、カーネルはifブロックの内側に届かないはずです!さらに、競合状態がなければエラーを再現できますが、はるかに複雑です。
v [2]のすべての出現をv [1]で置き換えると、エラーが消えてしまうことをどのように説明できますか? – thomas
@thomeas:コードを変更するので、コンパイラが発行するカーネルのレジスタフットプリントを変更します。 CUDAコンパイラは非常に積極的に最適化戦略を実行しますが、小さな変更でもイディオムやパターン識別パスがトリガされ、結果としてコードが小さくなります。変更したストレージをメモリ内の隣接する位置に移動することによって、レジスタを保存することができます。リンク先の指示に従って、あなた自身で簡単に確認できます。 – talonmies
説明をありがとう!私はレジスタの使用法を--ptxas-options = -vでテストしました。カーネルが34個のレジスタを使用していることを確認できました。今私は、レジスタのこの重い使用の理由は、どのように私はこれを減らすことができるのか理解する必要があります。 – thomas