我想知道为什么我的前几千个结果是正确的,然后我在cuda编程中得到了旧的值? #包括“opencv2\opencv.hpp” #包括 #包括 #包括 使用名称空间cv; 使用名称空间std; #定义计数200000 __全球的__ 无效子阵列(int*a、int*b、int-size) { int id=blockIdx.x*blockDim.x+threadIdx.x; 如果(id

我想知道为什么我的前几千个结果是正确的,然后我在cuda编程中得到了旧的值? #包括“opencv2\opencv.hpp” #包括 #包括 #包括 使用名称空间cv; 使用名称空间std; #定义计数200000 __全球的__ 无效子阵列(int*a、int*b、int-size) { int id=blockIdx.x*blockDim.x+threadIdx.x; 如果(id,opencv,cuda,nvidia,Opencv,Cuda,Nvidia,当我的内核运行时,它首先给出几个值,即差值正确,然后开始显示旧值?我做错了什么?我是noob,虽然我认为这些是我选错的块和线程的数量。 我的gpu CC是3.2您的代码中至少有2个错误 如前所述,内核假设每个像素有1个线程。您必须启动足够的线程来覆盖图像中的所有像素。我们可以通过增加块数来解决这个问题 您使用的复制操作的大小不正确。image1和image2数组都指定为int数组,内核相应地接受int*参数。您(显然)加载了一个无符号字符图像,但在加载该图像的过程中,您已将每个像素从8位量转换为

当我的内核运行时,它首先给出几个值,即差值正确,然后开始显示旧值?我做错了什么?我是noob,虽然我认为这些是我选错的块和线程的数量。
我的gpu CC是3.2

您的代码中至少有2个错误

  • 如前所述,内核假设每个像素有1个线程。您必须启动足够的线程来覆盖图像中的所有像素。我们可以通过增加块数来解决这个问题

  • 您使用的复制操作的大小不正确。
    image1
    image2
    数组都指定为
    int
    数组,内核相应地接受
    int*
    参数。您(显然)加载了一个
    无符号字符
    图像,但在加载该图像的过程中,您已将每个像素从8位量转换为32位量:

    #include "opencv2\opencv.hpp"
    #include <stdint.h>
    #include <stdio.h>
    #include <cuda.h>
    
    using namespace cv;
    using namespace std;
    #define count 200000 
    
    
    __global__
    void SubArrays(int * a, int * b, int size)
    {
        int id = blockIdx.x * blockDim.x + threadIdx.x;
    
        if (id < size)
        {
            a[id] -= b[id];
        }
    
    }
    
    
    int image1[count];
    int image2[count];
    
    int main(int argv, char** argc)
    {
    
        Mat im1 = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
        Mat im2 = imread("2.jpg", CV_LOAD_IMAGE_GRAYSCALE);
        int size = (im1.rows*im1.cols);
    
        printf("size: %d \n\n\n\n", size);
    
        int i = 0;
    
        for (int r = 0; r < im1.rows; r++)
        {
            for (int c =0; c< im1.cols; c++,i++)
            {
                image1[i] = im1.at<uint8_t>(r, c);
                image2[i] = im2.at<uint8_t>(r, c);
            }
        }
    
    
        printf("This is first image array's first 5 elements\n\n");
        for (int b = 0; b < 5; b++)
        {
            printf("%d\n",image1[b]);
        }
    
        printf("This is second image array's first 5 elements\n\n");
        for (int b = 0; b < 5; b++)
        {
            printf("%d\n", image2[b]);
        }
    
        int * h_a = image1;
        int * h_b = image2;
    
        int * d_a;
        int * d_b;
    
        cudaMalloc(&d_a, sizeof(char)*size);
        cudaMalloc(&d_b, sizeof(char)*size);
    
        cudaMemcpy(d_a, h_a, sizeof(char)*size, cudaMemcpyHostToDevice);
        cudaMemcpy(d_b, h_b, sizeof(char)*size, cudaMemcpyHostToDevice);
    
        SubArrays << <1, 1024 >> >(d_a, d_b, size);
    
        cudaMemcpy(h_a, d_a, sizeof(char)*size, cudaMemcpyDeviceToHost);
        printf("calculating result\n\n");
    
        for (int check = 0; check < size ; check++)
        {
            printf("%d \n", h_a[check]);
        }
    
        cudaFree(d_a);
        cudaFree(d_b);
    
        return 0;
    }
    
    sizeof(char)
    的使用不正确。您现在正在处理
    int
    数量,您应该在任何地方使用
    sizeof(int)

  • 下面的工作示例修复了这些问题,并且似乎在删除openCV依赖项的情况下工作正常:

    cudaMemcpy(d_a, h_a, sizeof(char)*size, cudaMemcpyHostToDevice);
                         ^^^^^^^^^^^
    
    $cat t1222.cu
    #包括
    #包括
    使用名称空间std;
    #定义计数200000
    __全球的__
    无效子阵列(int*a、int*b、int-size)
    {
    int id=blockIdx.x*blockDim.x+threadIdx.x;
    如果(id<大小)
    {
    a[id]=b[id];
    }
    }
    int image1[计数];
    int image2[计数];
    int main(int argv,字符**argc)
    {
    int i=0;
    对于(i=0;i(d_a、d_b、大小);
    cudaMemcpy(h_a,d_a,sizeof(int)*size,cudamemcpydevicetoost);
    printf(“计算结果\n\n”);
    for(int check=0;check

    我始终建议您在CUDA代码出现问题时使用(尽管我没有在此处添加它),并使用
    CUDA memcheck
    (如上所述)运行代码。

    TL/DR。听起来像是某个地方的整数溢出。为什么您只运行1024个线程的1个块?如果图像超过1024像素,那么大量的图像将未经处理。首先了解CUDA不是C!不要添加错误的标记。@talonmes那么我应该使用多少块和线程?我的图像大小约为340*507,接近2 lac。@Olaf好的,先生,我很抱歉,先生,这真的帮了我的忙!!解释得很透彻!!多谢各位
    cudaMemcpy(d_a, h_a, sizeof(char)*size, cudaMemcpyHostToDevice);
                         ^^^^^^^^^^^
    
    $ cat t1222.cu
    #include <stdint.h>
    #include <stdio.h>
    
    using namespace std;
    #define count 200000
    
    
    __global__
    void SubArrays(int * a, int * b, int size)
    {
        int id = blockIdx.x * blockDim.x + threadIdx.x;
    
        if (id < size)
        {
            a[id] -= b[id];
        }
    
    }
    
    
    int image1[count];
    int image2[count];
    
    int main(int argv, char** argc)
    {
    
        int i = 0;
        for (i = 0; i < count; i++)
            {
                image1[i] = 3;
                image2[i] = 1;
            }
    
        int size = count;
        printf("This is first image array's first 5 elements\n\n");
        for (int b = 0; b < 5; b++)
        {
            printf("%d\n",image1[b]);
        }
    
        printf("This is second image array's first 5 elements\n\n");
        for (int b = 0; b < 5; b++)
        {
            printf("%d\n", image2[b]);
        }
    
        int * h_a = image1;
        int * h_b = image2;
    
        int * d_a;
        int * d_b;
    
        cudaMalloc(&d_a, sizeof(int)*size);
        cudaMalloc(&d_b, sizeof(int)*size);
    
        cudaMemcpy(d_a, h_a, sizeof(int)*size, cudaMemcpyHostToDevice);
        cudaMemcpy(d_b, h_b, sizeof(int)*size, cudaMemcpyHostToDevice);
    
        SubArrays << <(count + 1023)/1024, 1024 >> >(d_a, d_b, size);
    
        cudaMemcpy(h_a, d_a, sizeof(int)*size, cudaMemcpyDeviceToHost);
        printf("calculating result\n\n");
    
        for (int check = 0; check < size ; check++)
        {
            if (h_a[check] != 2){printf("mismatch at %d, was: %d  should be 2\n", check, h_a[check]); return -1;}
        }
        printf("Success!\n");
        cudaFree(d_a);
        cudaFree(d_b);
    
        return 0;
    }
    $ nvcc -o t1222 t1222.cu
    $ cuda-memcheck ./t1222
    ========= CUDA-MEMCHECK
    This is first image array's first 5 elements
    
    3
    3
    3
    3
    3
    This is second image array's first 5 elements
    
    1
    1
    1
    1
    1
    calculating result
    
    Success!
    ========= ERROR SUMMARY: 0 errors
    $