Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 与OpenCL加权相乘,未覆盖全范围?_C++_C++11_Opencl_Gpgpu_Opencv3.0 - Fatal编程技术网

C++ 与OpenCL加权相乘,未覆盖全范围?

C++ 与OpenCL加权相乘,未覆盖全范围?,c++,c++11,opencl,gpgpu,opencv3.0,C++,C++11,Opencl,Gpgpu,Opencv3.0,我正在编写一个内核来处理索引的加权乘法。 我的意思是I*vec[I]。 我希望尽可能高效地使用我的计算单元(CL\u设备\u最大计算单元),而不超过我的最大工作组大小(CL\u内核\u工作组大小) 为此,我编写了以下内核: wght_mul.cl: #ifdef MU_ND __kernel void kmu(__global const int* _hist, const ulong _total, __global int* _tmp) { int id = get_global_

我正在编写一个内核来处理索引的加权乘法。 我的意思是
I*vec[I]
。 我希望尽可能高效地使用我的计算单元(
CL\u设备\u最大计算单元
),而不超过我的最大工作组大小(
CL\u内核\u工作组大小

为此,我编写了以下内核:

wght_mul.cl:

#ifdef MU_ND

__kernel void kmu(__global const int* _hist, const ulong _total, __global int* _tmp)
{
    int id = get_global_id(0)*kercn;
    const int lid = get_local_id(0);
    const int gid = get_group_id(0);

    const int gsz = get_global_size(0);
    const int lsz = get_local_size(0);

    int sum = 0;

    #if kercn == 4
    int4 sum4 = (int4)(0.f);
    #elif kercn == 8
    int8 sum8 = (int8)(0.f);
    #endif

    for(int grain = CU*WGS*kercn;id<_total;id+=grain)
    {
        #if kercn == 1
        sum += *(_hist+id) * id;
        #elif kercn == 4
        int4 idx = (int4)(id,id+1,id+2,id+3);
        int4 val = vload4(0,_hist+id);

        val*=idx;

        sum4 += val;
        #elif kercn == 8
        int8 idx = (int8)(id,id+1,id+2,id+3,id+4,id+5,id+6,id+7);
        int8 val = vload8(0,_hist+id);

        val*=idx;

        sum8 += val;
        #else
        #pragma unroll
        for(int i =0;i<kercn;i++)
            sum += *(_hist+id+i) * (id+i);

        #endif
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    #if kercn == 4
    sum = sum4.s0 + sum4.s1 + sum4.s2 + sum4.s3;
    #elif kercn == 8
    sum = sum8.s0 + sum8.s1 + sum8.s2 + sum8.s3 + sum8.s4 + sum8.s5 + sum8.s6 + sum8.s7;
    #endif

    *(_tmp+gid) += sum;

    printf("kercn %d\n",kercn);

    //printf("%d %d %d %d %d\n",id,lid,gid,gsz,lsz);
}

#endif
\ifdef MU\ND
__内核无效kmu(uuuu全局常量int*u历史、常量ulong总数、_uuu全局int*u tmp)
{
int id=获取全局id(0)*kercn;
const int lid=获取本地id(0);
const int gid=get_group_id(0);
const int gsz=获取全局大小(0);
const int lsz=获取本地大小(0);
整数和=0;
#如果kercn==4
int4 sum4=(int4)(0.f);
#elif kercn==8
int8sum8=(int8)(0.f);
#恩迪夫

对于(int grain=CU*WGS*kercn;id您必须知道,内核函数中的局部变量使用的寄存器文件空间非常有限。每个局部变量使用8字节而不是4字节将导致每个工作项需要更多寄存器。GPU内核之间的共享寄存器文件不足以在我同时也是


您可以使用GPU分析工具找出每种情况下所需的寄存器文件并对其进行优化。

您实际上应该拥有比计算单元多得多的工作组。例如,当某个工作组由于内存读取而暂停时,则可以同时执行另一个工作组。请更具体地说明当前结果和预期结果。感谢您的回答。我用顺序代码生成的预期结果给出了我希望使用并行代码得到的结果。我知道必须有比计算单元更多的工作组。这段代码后面的想法是了解如何使用opencl进行并行reduce。这段代码的灵感来自opencv的ocl_clachist1函数(module/imgproc/src/histogram.cpp)。因此,如果您注意使用kercn==vec.total()/globalsize获取组id(0)(对于此代码),您的id将永远不会超过计算单元数。
#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>

#include <fstream>
#include <sstream>
#include <algorithm>

int main()
{
    cv::Mat vec = cv::Mat::zeros(1,65536,CV_32SC1);
    cv::Mat idx = cv::Mat::zeros(1,65536,CV_32SC1);

    std::iota(idx.begin<int>(),idx.end<int>(),0);

    std::for_each(vec.begin<int>(),vec.end<int>(),[&](int& v){ v = cv::theRNG().uniform(0,1000);});


    // MY CODE

    cv::UMat uvec;
    cv::UMat utmp;

    vec.copyTo(uvec);

    std::ifstream file_stream("../test/wght_mul.cl");
    std::ostringstream file_buf;

    file_buf<<file_stream.rdbuf();

    cv::ocl::ProgramSource source(file_buf.str());

    const cv::ocl::Device& dev = cv::ocl::Device::getDefault();

    std::size_t wgs = dev.maxWorkGroupSize();
    std::size_t compute_units = dev.maxComputeUnits();

    std::size_t kercn = 8;

    std::size_t globalsize = wgs*compute_units;
    std::size_t localsize = wgs;


    cv::ocl::Kernel k("kmu",source,cv::format("-D MU_ND -D CU=%ld -D WGS=%ld -D kercn=%ld ",compute_units,wgs,kercn));

    k.run(1,&globalsize,&localsize,false);


    utmp = cv::UMat::zeros(compute_units,1,CV_32SC1);

    k.args(cv::ocl::KernelArg::PtrReadOnly(uvec),uvec.total(),cv::ocl::KernelArg::PtrWriteOnly(utmp));

    k.run(1,&globalsize,&localsize,false);

    std::cout<<"utmp : "<<utmp.getMat(cv::ACCESS_RW)<<std::endl;

    // RESULT EXPECTED

    cv::multiply(vec,idx,vec);

    std::cout<<"result expected : "<<cv::sum(vec)(0)<<" results using my kernel : "<<cv::sum(utmp)(0)<<std::endl;

    return EXIT_SUCCESS;
}