在GPU上添加值

时间:2013-04-04 03:17:39

标签: cuda

我有一个名为Product的课程。

每个产品都有一个值,我想在GPU上添加这些值。我在主机端填充了我的阵列

int * h_A, * d_A;
    h_A = (int*) malloc(enterNum * sizeof(int));
    cudaMalloc((void **) &d_A, enterNum * sizeof(int));



    Product p("Product", price);

    h_A[i] = p.getValue();

    while (i < enterNum) {
        i++;
        cout << "Enter product name:";
        cin >> desc;
        cout << "Enter product price:";
        cin >> price;
        Product p("Product", price);

        h_A[i] = p.getValue();
    }


    cudaMemcpy(d_A, h_A, enterNum, cudaMemcpyHostToDevice);
    priceSum<<<enterNum, 1024>>>(d_A,enterNum,result);

    int  result2 = 0;

    cudaMemcpy(result, result2, enterNum, cudaMemcpyDeviceToHost);

这里cudaMemcpy函数给出错误,因为我不使用指针。我能在这做什么?我不需要在这里使用指针不是吗?

这是我的求和函数:

__global__ void priceSum(int *dA, int count, int result) {

    int tid = blockIdx.x;

    if (tid < count){
        result+= dA[tid];
    }
}

完整代码:

using namespace std;
#include "cuda_runtime.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>

class Product {
private:
    char * description;
    int productCode;
    int value;
    static int lastCode;
public:
    Product(char* descriptionP, int valueP) {

        productCode = ++lastCode;
        value = valueP;
        description = new char[strlen(descriptionP) + 1];
        strcpy(description, descriptionP);
    }

    Product(Product& other) {
        productCode = ++lastCode;
        description = new char[strlen(other.description) + 1];
        strcpy(description, other.description);
    }

    ~Product() {
        delete[] description;
    }

    char* getDescription() const {
        return description;
    }

    void setDescription(char* description) {
        this->description = description;
    }

    int getValue() const {
        return value;
    }

    void setValue(int value) {
        this->value = value;
    }

};

int Product::lastCode = 1000;

__global__ void priceSum(int *dA, int count, int * result) {

    int tid = blockIdx.x;

    if (tid < count)
        result+= dA[tid];

}

int main(void) {

    int enterNum, price, * result = 0;
    string desc;
    const char * desc2;


    cout << "How many products do you want to enter?";
    cin >> enterNum;

    int * h_A, * d_A;
    h_A = (int*) malloc(enterNum * sizeof(int));
    cudaMalloc((void **) &d_A, enterNum * sizeof(int));



    int i = 0;

    while (i < enterNum) {

        cout << "Enter product name:";
        cin >> desc;
        cout << "Enter product price:";
        cin >> price;

        Product p("Product", price);
        h_A[i] = p.getValue();
        i++;
    }


    cudaMemcpy(d_A, h_A, enterNum * sizeof(int), cudaMemcpyHostToDevice);
    priceSum<<<enterNum, 1>>>(d_A,enterNum,result);

    int  result2 = 0;

    cudaMemcpy(&result2, result, enterNum, cudaMemcpyDeviceToHost);
    cout << result2;

    return 0;
}

1 个答案:

答案 0 :(得分:2)

您应该在主机代码中显示result的定义,但我认为它是:

int result;

基于您如何将其传递给priceSum内核。

这里有1个以上的问题。

  1. priceSum内核中,您将dA []中的值相加并将答案存储在result中。但是你已经通过值将变量result传递给内核而不是通过引用传递 ,所以你要修改的值是函数的本地值,并且不会显示其他任何地方。当C中的函数需要修改通过参数列表传递给它的变量,并且修改后的变量将显示在函数调用上下文中时,必须通过引用传递参数(即使用指针而不是按值。请注意,这是基于C编程语言的,并不是特定于CUDA。因此,您应该将内核定义重写为:

    __global__ void priceSum(int *dA, int count, int *result) {
    
  2. 关于您的cudaMemcpy调用,有几个问题需要清理。首先,我们需要使用cudaMalloc正确创建result的存储(在调用内核之前,因为内核会在那里存储内容。)接下来,我们需要修复cudaMemcpy调用本身的参数列表。因此,您的主机代码应该重写为:

    cudaMemcpy(d_A, h_A, enterNum, cudaMemcpyHostToDevice);
    int *result;
    cudaMalloc((void **)&result, sizeof(int));
    priceSum<<<enterNum, 1024>>>(d_A,enterNum,result);
    
    int  result2 = 0;
    
    cudaMemcpy(&result2, result, sizeof(int), cudaMemcpyDeviceToHost);
    
  3. 您的代码似乎存在其他问题,包括线程和块的数据分组。但是你没有向我展示足够的程序来理解它。因此,我要指出,您的代码只显示result(和result2)的单个值,但是编写内核的方式,每个线程都会添加其值dA[tid]result。你不能让一堆线程都在没有控制机制的情况下更新全局内存中的单个值,并期望获得合理的结果。像这样的问题通常最好用经典的并行缩减算法来处理,但为了简单起见,尝试使某些东西工作,你可以使用atomics

    atomicAdd(result, dA[tid]);
    
  4. 抱歉,你的内核完全没有意义。您使用blockIdx.x作为tid变量,但请注意blockIdx.x对于特定块中的每个线程相同的数字。所以继续让每个线程以这种方式将dA[tid]添加到result只是没有意义。我相信如果你将内核调用更改为:

    会更有意义
    priceSum<<<enterNum, 1>>>(d_A,enterNum,result);