内核调用后 CUDA 数组设置为 0

CUDA Array set to 0 after kernel call

我有一个包含 3 个数组的简单程序,它计算第三个数组有多少为 0,并且第一个和第二个具有相同的值。当它为真时,增加另一个数组索引。 问题是:

  1. 如果内核只有第一个if() then函数数组A永远为0

  2. 如果我插入 if() then else 函数,数组 A 的值在索引 = 2 后设置为 0,并且不计算 A、B、C=0[=13 时的状态=]

这是代码

#include <stdio.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <stdlib.h>
#include <cuda_runtime_api.h>

// Kernel that executes on the CUDA device
__global__ void square_array(float *a, float *b, float *c, float *res)
{
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (a[idx]=b[idx] && c[idx]==0) {
        res[0]++;
    }
    else if (a[idx]=b[idx] && c[idx]==1){
        res[1]++;
    }

}

// main routine that executes on the host
int main(void)
{
    float  *a_h, *a_d;  // Pointer to host & device arrays
    float  *b_h, *b_d;  // Pointer to host & device arrays
    float  *c_h, *c_d;  // Pointer to host & device arrays
    float  *res_h, *res_d;  // Pointer to host & device arrays

    const int N = 10;  // Number of elements in arrays
    size_t size = N * sizeof(float);
    //size_t size_s = 4 * sizeof(float);
    a_h = (float *)malloc(size);        // Allocate array on host
    cudaMalloc((void **) &a_d, size);   // Allocate array on device
    b_h = (float *)malloc(size);        // Allocate array on host
    cudaMalloc((void **) &b_d, size);   // Allocate array on device
    c_h = (float *)malloc(size);        // Allocate array on host
    cudaMalloc((void **) &c_d, size);   // Allocate array on device
    res_h = (float *)malloc(size);        // Allocate array on host
    cudaMalloc((void **) &res_d, size);   // Allocate array on device

    // Initialize host array and copy it to CUDA device
    //  for (int i=0; i<N; i++) a_h[i] = (float)i;
    for (int i=0; i<N; i++) a_h[i] = (float)i;
    for (int i=0; i<N; i++) b_h[i] = (float)i;
    for (int i=0; i<N; i++) c_h[i] = (float)i;
    for (int i=0; i<4; i++) res_h[i] = 0;


    cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice);
    cudaMemcpy(b_d, b_h, size, cudaMemcpyHostToDevice);
    cudaMemcpy(c_d, c_h, size, cudaMemcpyHostToDevice);
    cudaMemcpy(res_d, res_h, size, cudaMemcpyHostToDevice);
    // Do calculation on device:
    int block_size = 8;
    int n_blocks = N/block_size + (N%block_size == 0 ? 0:1);
    square_array <<< n_blocks, block_size >>> (a_d, b_d, c_d, res_d);
    // Retrieve result from device and store it in host array
    cudaMemcpy(a_h, a_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
    cudaMemcpy(b_h, b_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
    cudaMemcpy(c_h, c_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
    cudaMemcpy(res_h, res_d, sizeof(float)*N, cudaMemcpyDeviceToHost);

    // Print results
    for (int i=0; i<N; i++){
        printf("%f A \n", a_h[i]);
    }
    for (int i=0; i<N; i++){
            printf("%f B \n", b_h[i]);
        }
    for (int i=0; i<N; i++){
            printf("%f C \n", c_h[i]);
        }
    for (int i=0; i<4; i++){
        printf("%f res \n", res_h[i]);
    }

    // Cleanup
    free(a_h); cudaFree(a_d);
    free(b_h); cudaFree(b_d);
    free(c_h); cudaFree(c_d);
    free(res_h); cudaFree(res_d);
}

抱歉,我解决了 problem.It 是错误输入 control = 而不是 true ==

除了 if (a[idx]=b[idx] && c[idx]==0) { 中的 = 应该是 == 正如你已经找到的(下面的 if 语句也是如此),至少有您的代码中的另外两个问题:

  1. 您没有检查线程索引是否超出数组的限制。因此,由于您使用的是 2 个块,每块 8 个线程,因此您有 16 个线程访问 10 个元素数组。为避免此问题,您需要将 N 作为内核参数传递并在某处添加 if ( idx < N )

  2. 你在 res 中并行积累,没有任何保护,导致各种竞争条件。这是一个非常典型的直方图问题,在文献(网络、书籍、CUDA 示例...)中有大量解释。一个快速解决方法(尽管可能不是最有效的方法)是使用原子操作,例如 atomicAdd。在你的例子中,行 res[0]++; 会变成 atomicAdd( &res[0], 1 );,而 res[1]++; 会变成(如你所猜)atomicAdd( &res[1], 1 );。对 float 的支持意味着您在使用至少 2.0.

  3. 的计算能力时编译代码

HTH