【发布时间】:2015-03-08 05:54:55
【问题描述】:
我在尝试使用 pyopencl 进行光线追踪程序时遇到了麻烦。
为了给您一些背景信息,该程序背后的想法是我在网格中有一组初始光子,它们仅在 z 分量上具有动量。它们通过具有空间相关折射率的透镜。几个时间间隔后,我尝试用光子的位置构建直方图
为此,我使用了 numpy 和 pyopencl。我首先用这种格式将光子排列成一个数组: [[X0,Y0,Z0,Kx0,KY0,KZ0], ..., [XN,YN,ZN,KxN,KYN,KZN]] 其中 0 -> N 是光子的指数。然后我将这个 numpy 数组传递给设备,以便计算是线性系统与 Runge Kutta 4 阶的简单积分。
我的代码尝试如下:
Python 主程序
# -*- coding: utf-8 -*-
import numpy as np
import pyopencl as cl
from pylab import *
if __name__ == "__main__":
# Photons grid
Lx = 1.0
Ly = 1.0
delta_x = 0.01
delta_y = 0.01
Nx = Lx / delta_x
Ny = Ly / delta_y
X,Y = np.mgrid[-Lx:Lx+delta_x:delta_x,-Ly:Ly+delta_y:delta_y]
X = X.ravel()
Y = Y.ravel()
Z = -10.0
Kx = 0.0
Ky = 0.0
Kz = 1.0
N_points = len(X)
# Arranging the initial photons on a grid to send to Device in form of [[X0,Y0, ...], [X1,Y1, ...], ....]
grid_h = []
for i in range(N_points):
grid_h.append(np.array([X[i], Y[i], Z, Kx, Ky, Kz], dtype=np.float32))
grid_h = array(grid_h)
# Time Parameters
Lt = np.float32(1.0) # Time interval between departure of the photons and arrival at the "screen"
delta_t = np.float32(0.1) # Time step
T = np.arange(0.0, Lt, delta_t)
# Device Init
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
MF = cl.mem_flags
# CL Source Read and Build
f = open("kernel_tracer_2.cl", "r")
Source = f.read()
prg = cl.Program(ctx, Source).build()
# Constant init
N0 = np.float32(1.0)
Nm = np.float32(0.05)
C0 = np.float32(3.0)
DR = np.float32(0.2)
# Execution; Sends Blocks of photons to device, evolves them step by step
grid_d = cl.Buffer(ctx, MF.READ_WRITE | MF.COPY_HOST_PTR, hostbuf=grid_h)
for t in T:
# Evolve every photon
time = np.float32(t)
prg.RK4Step(queue, grid_h.shape, None, time, delta_t, N0, Nm, C0, DR, grid_d)
cl.enqueue_copy(queue, grid_h, grid_d)
X = grid_h[:, 0]
Y = grid_h[:, 1]
# Plotting
figure(1)
plt.plot(X,Y,'.')
figure(2)
H, xedges, yedges = histogram2d(X,Y, bins=50)
fig = plt.figure(figsize=(7, 3))
ax = fig.add_subplot(131)
ax.set_title('imshow: equidistant')
im = plt.imshow(H, interpolation='nearest', origin='low',
extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
show()
设备代码 (kernel_tracer_2.cl)
float8 f(float t, float N0, float Nm, float C0, float DR,
float8 q)
{
const float ind = N0 + Nm * exp(-(q.s0*q.s0 + q.s1*q.s1 + q.s2*q.s2)/(DR*DR));
const float np = sqrt(q.s3*q.s3 + q.s4*q.s4 + q.s5*q.s5);
const float c1 = C0 / (ind * np);
const float c2 = -2.0 * C0 * Nm *exp(-(q.s0*q.s0 + q.s1*q.s1 + q.s2*q.s2)/(DR*DR)) / (ind * ind * DR * DR);
float8 v;
v.s0 = c1 * q.s3;
v.s1 = c1 * q.s4;
v.s2 = c1 * q.s5;
v.s3 = c2 * q.s0;
v.s4 = c2 * q.s1;
v.s5 = c2 * q.s2;
return v;
}
__kernel void RK4Step(float t, float dt, float N0, float Nm, float C0, float DR, __global float8 *p){
const int gid = get_global_id(0);
float8 k, qm,qs;
//k1
k = f(t, N0, Nm ,C0, DR, p[gid]);
qs = p[gid] + dt * k/6.0;
qm = p[gid] + 0.5 * dt * k;
//k2
k = f(t+0.5*dt, N0, Nm ,C0, DR, qm);
qs += dt * k/3.0;
qm = p[gid] + 0.5 * dt * k;
//k3
k = f(t+0.5*dt, N0, Nm ,C0, DR, qm);
qs += dt * k/3.0;
qm = p[gid] + dt * k;
//k4
k = f(t + dt, N0, Nm ,C0,DR, qm);
qs += dt * k/6.0;
//update photon
p[gid] = qs;
}
每当我运行代码时,我都会收到以下错误:
Traceback (most recent call last):
File "path here", line 73, in <module>
cl.enqueue_copy(queue, grid_h, grid_d)
File "C:\Python27\lib\site-packages\pyopencl-2014.1-py2.7-win- amd64.egg\pyopencl\__init__.py", line 1090, in enqueue_copy
return _cl._enqueue_read_buffer(queue, src, dest, **kwargs)
RuntimeError: clEnqueueReadBuffer failed: out of resources
第 73 行是:cl.enqueue_copy(queue, grid_h, grid_d) 那是当我尝试将计算结果复制回设备时。
现在是这样。我在 GTX970 上收到此错误。我在 Titan 中尝试了这段代码,它运行正常,直到我将 delta_x 和 delta_y 更改为低于 0.01 的值。另一方面,我尝试使用旧的 Mobility Radeon HD 5145 在我的笔记本电脑上运行代码,它运行良好。我知道这是一个不同的 SDK,但这让我感到困惑。 我还尝试将 delta_x 和 delta_y 都更改为 0.1 来测试它,我没有收到任何错误,但与 Titan 和我的笔记本电脑的结果相比,结果都是错误的。
我有来自 nvidia 的最新驱动程序和 sdk。
很抱歉这篇长文,但我一直在努力解决这个问题,但不知道是什么原因造成的。我已尝试发布所有我认为相关的信息。
【问题讨论】:
标签: python opencl gpgpu raytracing pyopencl