【问题标题】:OpenCL code not working on larger datasetsOpenCL 代码不适用于更大的数据集
【发布时间】:2023-03-15 10:50:01
【问题描述】:

我正在尝试在 OpenCL/C++ 中编写排序函数和求和函数。然而,虽然这两个函数在较小的数据集上都可以正常工作,但都不能在任何显着长度的数据集上工作。我尝试使用的数据集大约有 200 万个条目,但函数在大约 500 个时停止工作。任何有关为什么这样做的帮助将不胜感激。 OpenCL 代码如下。

编辑:现在只显示与总和完全相关的代码(根据请求)。

kernel void sum(global const double* A, global double* B) {
    int id = get_global_id(0);
    int N = get_global_size(0);

    B[id] = A[id];

    barrier(CLK_GLOBAL_MEM_FENCE);

    for (int i = 1; i < N/2; i *= 2) { //i is a stride
        if (!(id % (i * 2)) && ((id + i) < N)) 
            B[id] += B[id + i];

        barrier(CLK_GLOBAL_MEM_FENCE);
    }
}

还有 C++ 代码:

        std::vector<double> temps(100000, 1);

        // Load functions
        cl::Kernel kernel_sum = cl::Kernel(program, "sum");

        // Set up variables
        size_t elements = temps.size();
        size_t size = temps.size() * sizeof(double);
        
        size_t workgroup_size = 10;
        size_t padding_size = elements % workgroup_size;

        // Sum
        if (padding_size) {
            std::vector<double> temps_padding(workgroup_size - padding_size, 0);
            temps.insert(temps.end(), temps_padding.begin(), temps_padding.end());
        }

        std::vector<double> temps_sum(elements);
        size_t output_size = temps_sum.size() * sizeof(double);

        cl::Buffer sum_buffer_1(context, CL_MEM_READ_ONLY, size);
        cl::Buffer sum_buffer_2(context, CL_MEM_READ_WRITE, output_size);

        queue.enqueueWriteBuffer(sum_buffer_1, CL_TRUE, 0, size, &temps[0]);
        queue.enqueueFillBuffer(sum_buffer_2, 0, 0, output_size);

        kernel_sum.setArg(0, sum_buffer_1);
        kernel_sum.setArg(1, sum_buffer_2);
        
        queue.enqueueNDRangeKernel(kernel_sum, cl::NullRange, cl::NDRange(elements), cl::NDRange(workgroup_size));
        queue.enqueueReadBuffer(sum_buffer_2, CL_TRUE, 0, output_size, &temps_sum[0]);
        double summed = temps_sum[0];

        std::cout << "SUMMED: " << summed << std::endl;

我试过到处看看,但我完全卡住了。

【问题讨论】:

  • “停止工作”是什么意思?什么失败了?在哪里?
  • 基本上,排序没有正确排序。它几乎可以 - 它有点像块排序,所以前 2/5 被排序,最后 2/5 被排序,然后中间只是一个乱码。对于求和,它只是求和不正确。我尝试了另一种求和方法,但数字太高,而提供的结果太低。
  • 你能把你的代码简化成一件事吗?这里的人不想涉足您的参数处理和错误检查等。将其归结为几行 C++ 和一个简短的 OpenCL 内核,它展示了您所看到的问题之一。
  • 我包含了所有内容,以便人们可以根据需要自行运行代码(尽管他们需要删除 Utils.h,哎呀)。老实说,我不知道问题出在哪里。我会把它简化为只显示总和的东西,但是是的。

标签: c++ opencl


【解决方案1】:

您正在尝试使用障碍进行工作组的同步。这行不通。 Barriers are for synchronising within work groups.

工作组之间的运行顺序并不明确;您只能在工作组使用这种归约算法。您可能需要使用第二个内核通道来组合来自各个工作组的结果,或者在主机 CPU 上执行此部分。 (或者修改你的算法以某种方式使用原子,等等)

【讨论】:

    猜你喜欢
    • 2016-01-31
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多