-2

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;
}
4

1 に答える 1

2

ホスト コードでの定義を表示する必要がありresultますが、次のように仮定します。

int result;

priceSumカーネルに渡す方法に基づいています。

ここには複数の問題があります。

  1. カーネルでは、priceSumdA[] の値を合計し、答えを に保存していますresult。ただし、変数を参照ではなくresultでカーネルに渡しているため、変更する値は関数に対してローカルであり、他の場所には表示されません。C の関数がパラメーター リストを介して渡された変数を変更する必要があり、変更された変数が関数呼び出しコンテキストに表示される場合、そのパラメーターを参照ではなく (つまり、ポインターを使用して)渡す必要があります。値による。これは C プログラミング言語に基づいており、CUDA に固有のものではないことに注意してください。したがって、カーネル定義を次のように書き換える必要があります。

    __global__ void priceSum(int *dA, int count, int *result) {
    
  2. cudaMemcpy 呼び出しに関しては、クリーンアップする必要があるいくつかの問題があります。まず、resultcudaMalloc を使用してストレージを適切に作成する必要があります (カーネルが呼び出される前に、カーネルがそこに何かを格納するため)。次に、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したがって、コードは(and )の値を 1 つしか示していないことを指摘しておきますresult2が、カーネルの記述方法では、各スレッドdA[tid]は の値をに追加しますresult。制御メカニズムなしでグローバル メモリ内の 1 つの値をすべて更新する多数のスレッドを持つことはできず、適切な結果が得られることは期待できません。このような問題は、通常、古典的な並列リダクション アルゴリズムで処理するのが最適ですが、簡単にするために、何かを機能させるために、atomicsを使用できます。

    atomicAdd(result, dA[tid]);
    
  4. 申し訳ありませんが、カーネルはまったく意味がありません。blockIdx.xを変数として使用していますが、これは特定のブロック内のすべてのスレッドで同じ数であることにtid注意してください。したがって、この方法ですべてのスレッドを追加することは意味がありません。カーネルの呼び出しを次のように変更すると、より理にかなっていると思います。blockIdx.xdA[tid]result

    priceSum<<<enterNum, 1>>>(d_A,enterNum,result);
    
于 2013-04-04T03:51:40.440 に答える