2014-12-29 71 views
0

我很難用PyOpenCl做一個基本的標量操作 基本上,我想要做的是給定一個浮點型數組,每個數組元素乘以一個標量浮點數並將結果放在新的緩衝區中。這應該很容易,但由於某種原因,它不應該如此。PyOpencl - 錯誤的參數傳遞給kernell

這是我正在使用的代碼:(帶_h變量是HOST變量;用_g變量是裝置變量)

import numpy as np 
import pyopencl as cl 
# Device Init 
ctx = cl.create_some_context() 
queue = cl.CommandQueue(ctx) 
MF = cl.mem_flags 

# Host Initial Variables 
a_h = np.array([1.0, 2.0, 3.0, 4.0]) 
b_h = np.float32(2.0) 

# DEVICE Variable Allocation 
a_g = cl.Buffer(ctx, MF.READ_ONLY | MF.COPY_HOST_PTR, hostbuf=a_h) 
c_g = cl.Buffer(ctx, MF.WRITE_ONLY, a_h.nbytes) 

# DEVICE's Kernel - Multiply each element of the array a_g by the scalar b_g and put the result on the array c_g 
source = """ 
__kernel void mult(float b_g, __global float *a_g, __global float *c_g){ 
    const int gid = get_global_id(0); 
    c_g[gid] = b_g * a_g[gid]; 
} 
""" 

prg = cl.Program(ctx, source).build() 
prg.mult(queue, a_h.shape, None, b_h, a_g, c_g) 

# Export The Result On The DEVICE Back To The HOST 
c_h = np.empty_like(a_h) 
cl.enqueue_copy(queue, c_h, c_g) 

# Output 
print c_h 

預期輸出中是

[2.0 4.0 6.0 8.0]

這是輸出:

[ 2.56000000e+002 5.12000000e+002 -1.73777009e+308 -1.73777009e+308] 

我不明白爲什麼。我已經嘗試閱讀PyOpenCL項目頁面,但我並不真正瞭解它的大部分內容。 我想我沒有正確地執行內核部分或內核調用部分。

我使用的內核,因爲這嘗試:

__kernel void mult(__global float *b_g, __global float *a_g, __global float *c_g) 

但預期它沒有工作,因爲我沒有創建B_G指針和我知道如何創建一個。錯誤是:

:2:39: error: parameter may not be qualified with an address space 
__kernel void mult(__global float b_g, __global float *a_g, __global float *c_g){ 
           ^

我這背後的主要想法很簡單:因爲我要使用這個值B_G共同的事情所有的工人,我想將它們放在全局內存一度讓每一位工人可以接受而不是重複每個工人的價值。

我相信這應該很簡單,但我是新來的並行計算,並不知道如何解決這個問題。

謝謝。

回答

0

在numpy中包含在同一個數組中的所有對象都有一個公共數據類型。該數據類型在數組的屬性dtype中指定。 (numpy.array doc,numpy datatypes

數組中的數據a_h是數據類型float64(64位浮點數)。由於您的內核需要32位浮點數(float32),因此它將這樣解釋a_h的數據。所以它會看到8個32位浮點數而不是4個64位浮點數。

爲了使其工作將a_h中的對象存儲爲float32。因此定義如下:

a_h = np.array([[1.0, 2.0, 3.0, 4.0], dtype=np.float32)