【问题标题】:OpenCL Matrix Multiplication - Getting wrong answerOpenCL 矩阵乘法 - 得到错误的答案
【发布时间】:2012-10-11 14:07:39
【问题描述】:

这是一个让我发疯的简单 OpenCL 矩阵乘法内核:

顺便说一句,我正在使用 pyopencl。

__kernel void matrixMul(  __global int* C,
                          __global int* A,
                          __global int* B,
                          int wA, int wB){

                int row = get_global_id(1); //2D Threas ID x
                int col = get_global_id(0); //2D Threas ID y

                //Perform dot-product accumulated into value
                int value = 0;
                for ( int k = 0; k < wA; k++ ){
                    value += A[row*wA + k] * B[k*wB+col];
                }
                C[row*wA+col] = value; //Write to the device memory
            }

在哪里(输入)

A = [72 45
     75 61]
B = [26 53 
     46 76]
wA = wB = 2

我得到的输出:

有时我会得到:

C = [3942 0
     0 5472]

否则我得到:

C = [3942 7236
     3312 5472]

但是输出应该是:

C = [3942 7236
     4756 8611]

我不知道我在这里犯了什么错误。我一整天都没有运气。

请帮我解决这个问题

这是完整的python代码:

import pyopencl as cl
import numpy as np
import os

ORDER = 2
LEN = ORDER*ORDER
ctx = cl.create_some_context()

commandQueue = cl.CommandQueue( ctx )

A = np.array((72, 45, 75, 61), dtype = np.int32)
B = np.array((26, 53, 46, 76), dtype = np.int32)
C = np.empty_like(A)

in_buf1 = cl.Buffer( ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR,
                 hostbuf = A )
in_buf2 = cl.Buffer( ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR,
                 hostbuf = B )
out_buf = cl.Buffer( ctx, cl.mem_flags.WRITE_ONLY, C.nbytes )

kernelSrc1 = """__kernel void
            matrixMul(  /*const int Mdim,
                        const int Ndim,
                        const int Pdim,*/
                        __global int* C,
                        __global int* A,
                        __global int* B,
                        int wA, int wB)
           {
                int row = get_global_id(1); //2D Threas ID x
                int col = get_global_id(0); //2D Threas ID y                

                //Perform dot-product accumulated into value
                int value = 0;
                for ( int k = 0; k < wA; k++ ){
                    value += A[row*wA + k] * B[k*wB+col];
                }
                C[row*wA+col] = value; //Write to the device memory
            }"""

program1 = cl.Program(ctx, kernelSrc1 ).build()
event1 = program1.matrixMul( commandQueue, (LEN, ), None,
                     out_buf, in_buf1, in_buf2, np.int32(ORDER), np.int32(ORDER));
event1.wait()

cl.enqueue_copy(commandQueue, C, out_buf)
print C

我正在使用 Python 2.7.x、pyopencl 2012.1、AMD APP SDK

【问题讨论】:

  • 我觉得不错。你确定你正确地读回了这些值(例如,试试“C[row*wA+col]=1;”看看你是否得到 C=[1,1,1,1])?
  • @Ian Mallett:我按照你说的做了,我得到 C=[1, 1, 1, 1]。所以我猜它没有读回这些值。顺便说一句,我将帖子编辑为我得到的实际错误答案,我的意思是我得到 c[1,0] = 0 而不是 4756。抱歉,我在发布问题之前先检查了一下。
  • 你能把python代码也贴出来,让我们看看你是怎么调用它的吗?
  • @K. Bradfford:我已经编辑了我的帖子以包含完整的 python 代码。
  • 预期输出的第一个值应该是 3942,而不是 3943。

标签: python opencl pyopencl


【解决方案1】:

您的全局大小 参数设置不正确。由于您在内核中使用了全局大小的两个维度,因此您需要将 全局大小 设置为 (ORDER,ORDER)。当你改变它时,你会得到:

[3942 7236
 4756 8611]

【讨论】:

  • 非常感谢。我得到了答案。但我还有一个问题,我正在使用矩阵宽度大小“wA”和“wB”来访问一维数组作为矩阵,因此如果我将全局大小作为一维数组传递,为什么不工作?
  • 因为您在内核中使用 X 和 Y 维度:int row = get_global_id(1); int col = get_global_id(0); 如果您真的想将全局大小设置为 (LEN,1),则需要计算行列值在你的内核中是这样的:int row = get_global_id(0) / wB; int col = get_global_id(0) % wA;
  • 但是这样可维护性较差。如果您按照现在的方式继续访问内核中的数据,使用 (ORDER, ORDER) 作为全局大小,并将您的 numpy 数组创建更改为:A = np.array(((72, 45), (75, 61)), dtype = np.int32); B = np.array(((26, 53), (46, 76)), dtype = np.int32),这样一切都匹配,您会更好当您和其他人阅读您的代码时。
  • 顺便说一句,当您将 np 数组声明为 1D 数组并像内核中的 2D 数组一样访问它时,内核仍然可以工作的原因是两个数组在内存中看起来完全相同numpy 和内核都关心。它们都是内存中的 4 个 32 位字节。
  • 非常感谢。您对我的帮助比您认为的要多,因为对我来说下一步将是在 OpenCL 中为我的项目实施 Hausdorff 距离,我需要了解 OpenCL 的基础知识。我已经连续 3 天了......现在很平静,还有很多东西要学......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多