【问题标题】:How should I properly design a vector normalization in opencl (work group sizes and kernels)我应该如何在opencl(工作组大小和内核)中正确设计向量归一化
【发布时间】:2016-02-03 04:46:59
【问题描述】:

我是 OpenCL 新手,在处理内存和本地工作组时遇到了一些麻烦。

我有一个四维数据结构,即 float[30][100][100][2025]。我目前按法线遍历前两个维度,并将生成的 2025x100 矩阵传递给以下 CPU 函数。

// num_columns = 100; num_rows = 2025
for (int column = 0; column < num_cols; column++){
    vector = matrix[column];

    float min = vector[0];
    float max = vector[0];
    for (int i = 0; i < num_rows; i++){
        if(vector[i] < min){min = vector[i];}
        if(vector[i] > max){max = vector[i];}
    }
    float diff = max-min + epsilon;

    for(int i = 0; i < num_rows; i++){
        vector[i] = (vector[i]-min)/diff; //MULTI-THREAD HERE
    }

    float mean = 0;
    for (int i = 0; i < num_rows; i++){
        mean += vector[i];
    }
    mean = mean/num_rows;

    for (int i = 0; i < num_rows; i++){
        vector[i] = vector[i]-mean + epsilon; //MULTI-THREAD HERE
    }

    float norm = 0;
    for (int i = 0; i < num_rows; i++){
        norm += vector[i]*vector[i];
    }
    norm = (float) sqrt(norm);

    if (norm > 0){
        for (int i = 0; i < num_rows; i++){
            vector[i] = vector[i]/norm; //MULTI-THREAD HERE
        }
    }
}

我已经评论了我认为可以从使用 OpenCL 中受益的地方。遍历每一列,将向量写入设备缓冲区,执行规范化,然后将其读回主机会很昂贵。 GPU(htc one m8 上的 Adreno 330)具有一次缓冲整个 2025x100 矩阵的内存。但是,我必须将其展平为一维浮点数组,并且我不知道如何一次仅在缓冲区的一部分(单个向量)上执行内核。

我已经阅读了很多有关 GPU 架构的内容,但我似乎无法理解设计此架构的正确方法,以及我是否应该利用本地工作组来解决问题。我希望我已经为某人提供了足够的信息来引导我朝着正确的方向前进。

编辑:我知道有一个内置的 CLnormalize 函数,但我需要实现三个不同的标准化函数,我不知道它们中的任何一个是否与内置函数匹配。无论如何我都尝试测试它,但我收到一个错误,它没有找到与 normalize(float *vector) 匹配的内置函数。

【问题讨论】:

    标签: opencl global local normalization


    【解决方案1】:

    您可以轻松地并行化 GPU 上的完整功能,而不仅仅是标记为“MULTI-THREAD HERE”的部分。在 OpenCL 中,您的线程/工作项被划分为本地工作组。在同一个工作组内,线程可以一起工作,使用本地共享内存共享数据并使用屏障进行同步。您可以处理每个工作组中的一列。每列是完全独立的,因此不需要工作组之间的同步。

    在每个工作组中,我们可以使用每个线程来处理向量的 4 或 8 个元素。 (如果您只处理每个工作项的元素,您的工作组将大于最大工作组大小)这里的棘手部分是如何并行计算向量的最大值、最小值和总和:这里我们可以使用并行编程原语称为“平行归约”。这是一个带有漂亮幻灯片的视频,解释了该技术: https://www.youtube.com/watch?v=siHYfH1RQ_s

    您可以将此技术用于向量、最小值和最大值的总和,以并行计算最小值、最大值和平均值。如果你同时做这三个,它甚至会比三个单独的减少快一点,因为你需要更少的同步。您还可以使用局部变量来存储 vector[i] 的临时结果,并且只在开始时读入 vector[i] 一次,并在完成对 vector[i] 的所有计算后在最后写回 vector[i] .这样可以节省大量内存带宽。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-13
      • 1970-01-01
      相关资源
      最近更新 更多