CUDA - 浮点数组的意外结果

时间:2013-09-15 09:27:56

标签: cuda nvidia

我遇到了一个我不明白的问题。我试图在设备中设置数组的值。使用int数组我这样做:

#define VECTOR_SIZE 8
int main()
{
    printf("Start\n");
    int *input_d;
    int *output_d;
    int output_h[VECTOR_SIZE];
    int input_h[VECTOR_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    int size = VECTOR_SIZE*sizeof(int);
    cudaMalloc(&input_d,size);
    cudaMalloc(&output_d,size);
    cudaMemcpy(input_d,input_h,size,cudaMemcpyHostToDevice);
    kernel<<<1,VECTOR_SIZE>>>(input_d,output_d);
    cudaMemcpy(output_h,output_d,size, cudaMemcpyDeviceToHost);
    cudaFree(input_d);
    cudaFree(output_d);
    return 0;
}

内核看起来像:

__global__ void kernel(int* input, int* output)
{
    int dx = threadIdx.x + (blockDim.x * blockIdx.x);
    output[dx] = dx;
}

输出(output_h)就像我预期的那样{0,1,2,3,4,5,6,7}。现在当我尝试在float数组上做同样的事情时:

#define VECTOR_SIZE 8
int main()
{
    printf("Start\n");
    float *input_d;
    float *output_d;
    float output_h[VECTOR_SIZE];
    float input_h[VECTOR_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    int size = VECTOR_SIZE*sizeof(float);
    cudaMalloc(&input_d,size);
    cudaMalloc(&output_d,size);
    cudaMemcpy(input_d,input_h,size,cudaMemcpyHostToDevice);
    kernel<<<1,VECTOR_SIZE>>>(input_d,output_d);
    cudaMemcpy(output_h,output_d,size, cudaMemcpyDeviceToHost);
    cudaFree(input_d);
    cudaFree(output_d);
    return 0;
}

with kernel:

__global__ void kernel(float* input, float* output)
{
    int dx = threadIdx.x + (blockDim.x * blockIdx.x);
    output[dx] = dx;
}

我在output_h变量中的设备上收到零数组。

处理float数组的完整代码:

#include "cuda_runtime.h"
#include <stdio.h>

#define VECTOR_SIZE 8

__global__ void kernel(float* input, float* output)//, int halfSize)
{
    int dx = threadIdx.x + (blockDim.x * blockIdx.x);
    output[dx] = dx;
} 

int main()
{
    printf("Start\n");
    float *input_d;
    float *output_d;
    float output_h[VECTOR_SIZE];
    float input_h[VECTOR_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 
    int size = VECTOR_SIZE*sizeof(float);
    cudaMalloc(&input_d,size);
    cudaMalloc(&output_d,size);
    cudaMemcpy(input_d,input_h,size,cudaMemcpyHostToDevice);
    kernel<<<1,VECTOR_SIZE>>>(input_d,output_d);
    cudaMemcpy(output_h,output_d,size, cudaMemcpyDeviceToHost);
    cudaFree(input_d);
    cudaFree(output_d);
    int i;
    for (i=1; i<=VECTOR_SIZE; i++)
    {
        printf("%d, ", output_h[i-1]);
    }
    getchar();
    return 0;
}

1 个答案:

答案 0 :(得分:3)

您发布的CUDA代码的整数和浮点版本都可以正常工作。唯一的错误是如何在浮点代码的情况下打印出内核返回的值:

int i;
for (i=1; i<=VECTOR_SIZE; i++)
{
    printf("%d, ", output_h[i-1]);
}

应改为

int i;
for (i=0; i<VECTOR_SIZE; i++)
{
    printf("%f, ", output_h[i]);
}

(请注意,打印浮点数需要%f格式。)

鉴于CUDA默认情况下使用C ++编译器作为主机代码,您可能更喜欢iostreamprintf - 无论输出类型如何都会有效,并且不会导致您看到的错误。如果我要编写示例的“通用”版本,它将如下所示:

#include <iostream>

template<typename T>
__global__ void kernel(T* output)
{
    int dx = threadIdx.x + (blockDim.x * blockIdx.x);
    output[dx] = dx;
}

template<typename T, int VECTOR_SIZE>
void do_run(void)
{
    T *output_d;
    T output_h[VECTOR_SIZE] = { 999 };
    size_t size = sizeof(output_h);
    cudaMalloc(&output_d,size);
    kernel<T><<<1,VECTOR_SIZE>>>(output_d);
    cudaMemcpy(output_h, output_d, size, cudaMemcpyDeviceToHost);
    for(int i=0; i<VECTOR_SIZE; i++)
        std::cout << output_h[i] << std::endl;

    cudaFree(output_d);
}

int main()
{
    std::cout << "Integer version" << std::endl;
    do_run<int, 8>();

    std::cout << "floating point version" << std::endl;
    do_run<float, 8>();

    return 0;
}

请注意,intfloat版本的输出代码可以不加改变地使用,从而消除了您在此处犯的错误。