Opencl 打开Cl。我只需要将代码转换为使用for循环中的两个工作项。目前它使用一个 spmv\u csr\u标量内核(const int num\u行, 常数int*ptr, 常数int*索引, 常量浮点*数据, 常量浮点*x, 浮点数*y) { int行=获取全局id(0); 如果(行数

Opencl 打开Cl。我只需要将代码转换为使用for循环中的两个工作项。目前它使用一个 spmv\u csr\u标量内核(const int num\u行, 常数int*ptr, 常数int*索引, 常量浮点*数据, 常量浮点*x, 浮点数*y) { int行=获取全局id(0); 如果(行数,opencl,Opencl,上面是将CSR格式的稀疏矩阵与列向量相乘的开放Cl代码。它在每个for循环中使用一个全局工作项。有人能帮助我在每个for循环中使用两个工作项吗?我是开放Cl的新手,即使修改最小的东西,也会遇到很多问题。请帮助我。这是我项目的一部分。我做了这样的并行,但我想让它更平行。如果可以的话请帮助我 单个工作项从第_行开始到第_行结束执行for循环。我希望这一行或for循环进一步分为两个部分,每个部分由单个工作项执行。我如何继续完成 这是我能想到的,但它返回了错误的输出 spmv_csr_scalar_ke

上面是将CSR格式的稀疏矩阵与列向量相乘的开放Cl代码。它在每个for循环中使用一个全局工作项。有人能帮助我在每个for循环中使用两个工作项吗?我是开放Cl的新手,即使修改最小的东西,也会遇到很多问题。请帮助我。这是我项目的一部分。我做了这样的并行,但我想让它更平行。如果可以的话请帮助我

单个工作项从第_行开始到第_行结束执行for循环。我希望这一行或for循环进一步分为两个部分,每个部分由单个工作项执行。我如何继续完成

这是我能想到的,但它返回了错误的输出

spmv_csr_scalar_kernel(const int num_rows,
                       const int * ptr,
                       const int * indices,
                       const float * data,
                       const float * x,
                       float * y )
{
    int row = get_global_id(0);
    if(row < num_rows)
    {
        float dot = 0;
        int row_start = ptr[row];
        int row_end = ptr[row+1];
        for (int jj = row_start; jj < row_end; jj++)
        {  
            dot += data[jj] * x[indices[jj]];
        }
        y[row] += dot;
    }
}
\uuuuu内核void mykernel(\uuuuu global int*colvector,
__全局int*val,
__全局整数*结果,
__全局整数*索引,
__全局int*rowptr,
__全局整数*同步)
{
__全局整数vals[8]={0,0,0,0,0,0,0};

对于(int i=0;i您需要使用工作组的数量和组id来实现这一点

__kernel void mykernel(__global int* colvector,
                       __global int* val,
                       __global int* result,
                       __global int* index,
                       __global int* rowptr,
                       __global int* sync )
{
    __global int vals[8]={0,0,0,0,0,0,0,0};
    for(int i=0;i<4;i++)
    {
        result[i]=0;
    }
    barrier(CLK_GLOBAL_MEM_FENCE);

    int thread_id=get_global_id(0);
    int warp_id=thread_id/2;
    int lane=(thread_id)&1;
    int row=warp_id;

    if(row<4)
    {
        int row_start = rowptr[row];
        int row_end = rowptr[row+1];
        vals[thread_id]=0;

        for (int i = row_start+lane; i<row_end; i+=2)
        {
            vals[thread_id]+=val[i]*colvector[index[i]];
        }

        vals[thread_id]+=vals[thread_id+1];

        if(lane==0)
        {
            result[row] += vals[thread_id];
        }
    }               
}
spmv\u csr\u scalar\u内核(常量int num\u行、常量int*ptr、常量int*索引、常量float*数据、常量float*x、float*y){
__本地浮点[64]点;//点积的本地内存。假设您最多要使用64项工作组。
int localId=get_local_id(0);//为jj循环提供最值
int localSize=get_local_size(0);//这是计算jj循环的工作项数
int nGroups=get_num_groups(0);//执行此内核的工作组数
for(int row=get_group_id(0);row
此内核将使用您想要完成所有工作的任意多个工作组。(ie组可以在多行上工作)这是通过将“if(row
我使用64作为本地内存大小的硬编码值。上面的内核可以很好地处理高达64的工作组大小。64在今天的许多设备上都是最佳的。您可以尝试使用其他硬编码值,或者通过传递一个_local参数来分配本地内存。

朋友,您的代码没有返回正确的输出。它的retur对于结果数组的第一个索引,所有剩余索引都为0。对于工作组、工作项、本地项的不同设置,返回的值不同。我应该如何设置enqueundrangekernel(……)调用?它将为不同的本地和全局项组合返回不同的答案。无错误。请尝试仅使用单个全局工作项(以及一个小矩阵,如果可以的话)。如果结果正确,请尝试使用16个全局和16个本地工作项来测试单个工作组。
spmv_csr_scalar_kernel(const int num_rows, const int * ptr, const int * indices, const float * data, const float * x, float * y) {

    __local float[64] dot; //local memory for dot product. assumes you want to use up to 64-item workgroups.
    int localId = get_local_id(0); //offest value for jj loop
    int localSize = get_local_size(0); //this is the number of work items computing the jj loop
    int nGroups = get_num_groups(0); //number of workgroups executing this kernel

    for (int row = get_group_id(0); row < num_rows; row += nGroups) {
        dot[localId] = 0;
        int row_start = ptr[row] + localId;
        int row_end = ptr[row + 1];
        for (int jj = row_start; jj < row_end; jj++) {
            dot[localId] += data[jj] * x[indices[jj]];
        }
        barrier(CLK_LOCAL_MEM_FENCE);

        //here's where work item #0 in the group sums the values stored in local memory
        if (localId == 0) {
            for (int i = 1; i < localSize; i++) {
                dot[0] += dot[i];
            }
            y[row] += dot[0]; //only a single write to the global memory location
            barrier(CLK_LOCAL_MEM_FENCE);
        }
    }