微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 2D 倾斜阵列减少 CUB 和

如何解决使用 2D 倾斜阵列减少 CUB 和

我正在尝试使用 CUB 和 float/double 类型的二维数组来执行求和。 虽然它适用于行+列的某些组合,但对于相对较大的数组,我在上次传输期间收到非法内存访问错误一个最小的例子如下:

#include <stdio.h>
#include <stdlib.h>

#include <cub/device/device_reduce.cuh>
#include "cuda_runtime.h"

#ifdef DP
#define real double
#else
#define real float
#endif

void generatedata(const int num,real* vec,real start,real finish) {
    real rrange = finish - start;
    for (auto i = 0; i < num; ++i)
        vec[i] = rand() / float(RAND_MAX) * rrange + start;
}

real reduce_to_sum(const int num,const real* vec) {
    real total = real(0.0);
    for (auto i = 0; i < num; ++i)
        total += vec[i];

    return total;
}

int main() {
    int rows = 2001;
    int cols = 3145;
    size_t msize = rows * cols;

    real* data = (real*)malloc(msize * sizeof(real));
    if (!data)
        return -999;

    generatedata(msize,data,0.,50.);
    real ref_sum = reduce_to_sum(msize,data);

    real* d_data_in = nullptr;
    real* d_data_out = nullptr;
    size_t pitch_in,pitch_out;
    cudaError_t err = cudamallocPitch(&d_data_in,&pitch_in,cols * sizeof(real),rows);
    if (err != cudaSuccess) {
        printf("data_in :: %s \n",cudaGetErrorString(err));
        return -999;
    }
    err = cudamallocPitch(&d_data_out,&pitch_out,rows);
    if (err != cudaSuccess) {
        printf("data_out :: %s \n",cudaGetErrorString(err));
        return -999;
    }

    err = cudamemset(d_data_in,rows * pitch_in);
    if (err != cudaSuccess) {
        printf("set data_in :: %s \n",cudaGetErrorString(err));
        return -999;
    }
    err = cudamemcpy2D(d_data_in,pitch_in,rows,cudamemcpyHostToDevice);
    if (err != cudaSuccess) {
        printf("copy data :: %s \n",cudaGetErrorString(err));
        return -999;
    }

    void* d_temp = nullptr;
    size_t   temp_bytes = 0;
    cub::DeviceReduce::Sum(d_temp,temp_bytes,d_data_in,d_data_out,rows * pitch_out);
    err = cudamalloc(&d_temp,temp_bytes);
    if (err != cudaSuccess) {
        printf("temp :: %s \n",cudaGetErrorString(err));
        return -999;
    }

    err = cudamemset(d_data_out,rows * pitch_out);
    if (err != cudaSuccess) {
        printf("set temp :: %s \n",cudaGetErrorString(err));
        return -999;
    }
    // Run sum-reduction
    cub::DeviceReduce::Sum(d_temp,rows * pitch_out);
    err = cudaGetLastError();
    if (err != cudaSuccess) {
        printf("reduction :: %s \n",cudaGetErrorString(err));
        return -999;
    }

    real gpu_sum = real(0.0);
    err = cudamemcpy(&gpu_sum,sizeof(real),cudamemcpyDevicetoHost);
    if (err != cudaSuccess) {
        printf("copy final :: %s \n",cudaGetErrorString(err));
        return -999;
    }

    printf("Difference in sum (h)%f - (d)%f = %f \n",ref_sum,gpu_sum,ref_sum - gpu_sum);

    if (data) free(data);
    if (d_data_in) cudaFree(d_data_in);
    if (d_data_out) cudaFree(d_data_out);
    if (d_temp) cudaFree(d_temp);
    cudaDeviceReset();
    return 0;
}

在“copy final ::”处抛出错误。我对为什么某些行 x 列有效而其他行无效的原因感到有些困惑。我确实注意到它是导致它的较大值,但无法理解。 任何建议将不胜感激。

解决方法

cub::DeviceReduce::Sum 的第 5 个参数应该是输入元素的数量。但是,rows * pitch_out 是以字节为单位的输出缓冲区的大小。

假设 pitch_in % sizeof(real) == 0,以下调用可能有效。

cub::DeviceReduce::Sum(d_temp,temp_bytes,d_data_in,d_data_out,rows * (pitch_in / sizeof(real)));

另请注意,cub::DeviceReduce::Sum 可能会在归约完成之前返回。在这种情况下,如果在执行过程中发生任何错误,cudaMemcpy 将报告此错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。