使用OpenCL的矩阵向量乘法

使用OpenCL的矩阵向量乘法,opencl,matrix-multiplication,multiplication,Opencl,Matrix Multiplication,Multiplication,我有两个不同的程序 首先使用opencl进行矩阵乘法。在我的GPU上,它产生了更好的结果,例如,在主机CPU上是0.2秒,而不是18秒 第二种是使用opencl进行矩阵向量乘法,它在GPU上的工作速度比在主机CPU上稍慢 原因是什么 这是内核 __kernel void matrixVectorMul(__global float* resultVector, __global float* matrixA, __global float* vectorB, int w

我有两个不同的程序

首先使用opencl进行矩阵乘法。在我的GPU上,它产生了更好的结果,例如,在主机CPU上是0.2秒,而不是18秒

第二种是使用opencl进行矩阵向量乘法,它在GPU上的工作速度比在主机CPU上稍慢

原因是什么

这是内核

__kernel void matrixVectorMul(__global float* resultVector,
    __global float* matrixA,
    __global float* vectorB, 
    int width_A)
{
    int tx = get_global_id(0); 

    float value = 0;
    for (unsigned int k = 0; k < width_A; ++k) {
        value += matrixA[tx * width_A + k] * vectorB[k];
    }

    resultVector[tx] = value;
}

在这种情况下,为了提高GPU效率,需要更多的工作项,每个输出值一个工作项是不够的,计算/内存访问率应该更高,即尽可能多次重用值


如果您感兴趣,我不久前已经写了几页关于这个问题的文章:。

在这种情况下,为了提高GPU的效率,需要更多的工作项每个输出值一个是不够的,并且计算/内存访问率应该更高,即在可能的情况下多次重用值


如果您感兴趣的话,我不久前已经写了几页关于这个问题的文章:。

您是否尝试过将本地内存用于vectorB?每个元素都由所有工作项读取,因此从本地读取是有意义的。我将本地内存大小硬编码为8192,但您可以自己使用这个数字。8192浮动是opencl 1.1/1.2的最大值

此外,如果可以的话,可以尝试使用16 64或128的倍数的工作组大小

__kernel void matrixVectorMul(__global float* resultVector,
    __global float* matrixA,
    __global float* vectorB, 
    int width_A)
{
    int tx = get_global_id(0);
    __local float vectB[4096*2];

    event_t copy_event = async_work_group_copy(vectB, vectorB, 4096*2, 0);
    wait_group_events(1,copy_event);

    float value = 0;
    for (unsigned int k = 0; k < width_A; ++k) {
        value += matrixA[tx * width_A + k] * vectB[k];
    }

    resultVector[tx] = value;
}

你有没有试过使用vectorB的本地内存?每个元素都由所有工作项读取,因此从本地读取是有意义的。我将本地内存大小硬编码为8192,但您可以自己使用这个数字。8192浮动是opencl 1.1/1.2的最大值

此外,如果可以的话,可以尝试使用16 64或128的倍数的工作组大小

__kernel void matrixVectorMul(__global float* resultVector,
    __global float* matrixA,
    __global float* vectorB, 
    int width_A)
{
    int tx = get_global_id(0);
    __local float vectB[4096*2];

    event_t copy_event = async_work_group_copy(vectB, vectorB, 4096*2, 0);
    wait_group_events(1,copy_event);

    float value = 0;
    for (unsigned int k = 0; k < width_A; ++k) {
        value += matrixA[tx * width_A + k] * vectB[k];
    }

    resultVector[tx] = value;
}

为什么要硬编码本地尺寸?CPU和GPU有非常不同的最佳本地工作组大小,例如,我的CPU有1024个,但我的GPU有64个。我想你可以尝试转置矩阵,从顺序内存读取中获益,现在它们是交错的。这个程序主要是为了演示。我使用另一个简单的程序获得了本地大小,该程序查询GPU的一些参数。我曾尝试将vectorB复制到内核中的本地数组中,我想,它必须放弃加速,但它无法编译。但是,如果我只是声明局部数组,而不尝试访问它的元素,它编译得很好。为什么要硬编码局部大小?CPU和GPU有非常不同的最佳本地工作组大小,例如,我的CPU有1024个,但我的GPU有64个。我想你可以尝试转置矩阵,从顺序内存读取中获益,现在它们是交错的。这个程序主要是为了演示。我使用另一个简单的程序获得了本地大小,该程序查询GPU的一些参数。我曾尝试将vectorB复制到内核中的本地数组中,我想,它必须放弃加速,但它无法编译。但是如果我只是声明局部数组,而不尝试访问它的元素,它编译得很好。一个加速的方法是同时计算同一个矩阵与多个向量的乘积。一个加速的方法是同时计算同一个矩阵与多个向量的乘积。
__kernel void matrixVectorMul(__global float* resultVector,
    __global float* matrixA,
    __global float* vectorB, 
    int width_A)
{
    int tx = get_global_id(0);
    __local float vectB[4096*2];

    event_t copy_event = async_work_group_copy(vectB, vectorB, 4096*2, 0);
    wait_group_events(1,copy_event);

    float value = 0;
    for (unsigned int k = 0; k < width_A; ++k) {
        value += matrixA[tx * width_A + k] * vectB[k];
    }

    resultVector[tx] = value;
}