Wrong result from Matrix multiplication on GPU Mac Pro AMD OpenCL

Viewed 185

Need help, I am trying to perform Matrix multiplication on my GPU using OpenCL. The results seem to very wrong but the dimension of the matrix is correct. I am not sure if there is some wrong pointer issue going on. Please help.

Tried on int and float(shouldn't matter) but both failed.

import pyopencl as cl
import numpy as np
import numpy.linalg as la
import datetime
import os
os.environ['PYOPENCL_COMPILER_OUTPUT'] = '1'

def openCL_multiplication(matrix1, matrix2):
    ctx = cl.create_some_context()
    queue = cl.CommandQueue(ctx)

    mf = cl.mem_flags
    a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=matrix1)
    b_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=matrix2)
    dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, matrix1.nbytes )


    prg = cl.Program(ctx, """
        __kernel void multiplymatrices( int size, __global float * matrix1, __global float * matrix2, __global float * res) {

        int i = get_global_id(1); 
        int j = get_global_id(0);

        res[i + size * j] = 0;

        for (int k = 0; k < size; k++)
        {
            res[i + size * j] += matrix1[k + size * i] * matrix2[j + size * k];
        }

        }
        """).build()

    t0 = datetime.datetime.now()
    print("Size:" + str(np.int32(len(matrix1))))
    print("a:" + str(a_buf))
    print("b:" + str(b_buf))
    prg.multiplymatrices(queue, matrix1.shape, None,np.int32(len(matrix1)) ,a_buf, b_buf, dest_buf)

    final_matrix = np.empty_like(matrix1)
    cl.enqueue_copy(queue, final_matrix , dest_buf)

    print (final_matrix)


    delta_t = datetime.datetime.now() - t0
    print ('OpenCL Multiplication: ' + str(delta_t))

    return final_matrix


M1 = np.array([[2,3],[1,4]])
M2 = np.array([[1,2],[3,4]])
print(M1)
print(M2)



res = openCL_multiplication(M1, M2)
print(res)

Output is as below: OpenCL Multiplication: 0:00:00.004049

[[ 0 0] [4323174168305532928 4323174168305532928]]

1 Answers

I don't really know anything about python or pyopencl, but your OpenCL kernel code looks OK. (Although I'd accumulate the result in a private variable and only write to res[i + size * j] once at the end; this will be much more efficient but the code should provide correct results as it stands.)

4323174168305532928 is 0x3BFF00003BFF0000, which at first glance looks to me like the binary representation of 2 32-bit floats back-to-back. So I suspect your kernel is fine but your handling of the buffers is incorrect - you're interpreting them as the wrong data types, 64-bit integers instead of floats. This is going to be pyopencl/python specific so I can't tell you the correct answer, but hopefully this puts you on the right track for working it out yourself, or perhaps someone else can chip in.

Related