2017-07-07 10 views
0

私はint配列ポインタとbool変数からなる "Coordinate"という名前のクラスを持っています。私はこのポインタをCUDAに送り、それを修正してCPUメモリに戻したいと思っています。ここで 別のクラスを介してCUDAメモリへの配列ポインタの転送

がCoordinate.hです:私はcudamain.cu CHECK1CHECK2に2つの グローバル機能してきた

#ifndef __COORDINATE_H 
#define __COORDINATE_H 

#include <stdlib.h> 
#include <cuda.h> 

using namespace std; 

class Coordinate { 

public: 
    int *array_pointer; 
    bool flag; 

    Coordinate() { flag = false; } 

    Coordinate(int array_length) { 
     flag = false; 
     array_pointer = new int[array_length]; 
     for (int i = 0; i < array_length; i++) { 
      array_pointer[i] = -1; 
     } 
    } 
}; 

#endif 

、両方の引数として座標がかかります。 Check1関数は、Check2がブール値フラグを変更するブール値フラグだけを変更し、配列も変更します。ここで

がcudamain.cuです:CHECK1 aとbと一緒に行きます

#include <iostream> 
#include <cuda.h> 
#include "Coordinate.h" 

using namespace std; 

__global__ void check1(Coordinate *ptr) { 
    c->flag = true; 
} 

__global__ void check2(Coordinate *c) { 
    c->flag = true; 
    for (int i = 0; i < 10; i++) { 
     c->array_pointer[i] = i; 
    } 
} 


int main() { 
    Coordinate *d_a, *d_b, a, b; 
    a = Coordinate(10); b = Coordinate(10); 

    size_t size = sizeof(Coordinate); 

    cudaMalloc((void**)&d_a, size); cudaMalloc((void**)&d_b, size); 
    cudaMemcpy(d_a, &a, size, cudaMemcpyHostToDevice); cudaMemcpy(d_b, &b, size, cudaMemcpyHostToDevice); 

    check1 << <1, 1 >> > (d_a); 
    cudaMemcpy(&a, d_a, size, cudaMemcpyDeviceToHost); 
    cout <<"d_a result-> " <<a.flag <<" " <<a.array_pointer[9] << endl; 

    check2 << <1, 1 >> > (d_b); 
    cudaMemcpy(&b, d_b, size, cudaMemcpyDeviceToHost); 
    cout << "d_b result-> " << b.flag << " " << b.array_pointer[9] << endl; 
    return 0; 
} 

私は2つの別々の座標オブジェクトを作っBはCHECK2で行きます。 bの両方が同じ方法で初期化されます。 I座標クラスの配列ポインタを初期化することができないよう

d_a result-> 1 -1 
d_b result-> 1 9 

異なる座標オブジェクトが異なる配列の長さを有していてもよい:

Iが得る結果は

d_a result-> 1 -1 
d_b result-> 0 -1 

期待される結果です。

+2

1. [正しいcudaエラーチェック](https://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime -api)。2. 'cuda-memcheck'でコードを実行します。私がそれをすると、 'check2'カーネルが不正な書き込みアクセスを行っていることがわかります –

+0

埋め込みポインタを持つクラスはCUDAで特別な処理を必要とします。 [これは](https://stackoverflow.com/a/15435592/1695960)の答えです。 –

+0

@RobertCrovella、カーネルからホストポインタにアクセスすることは合法ですか? –

答えて

1

をderefernnすることで、CUDAカーネルからホストメモリにアクセスすることはできません。 cudaMallocManaged()を使用してください。だからあなたのプログラムは動作しません。ホストとデバイスの両方から同じメモリにアクセスする場合はthis Parallel4All postを読んでください。別のalternativeは@RobertCrovellaにリンクされていて、デバイス側のメモリの割り当てを含みます。

しかし、率直に言って、Coordinateという名前のクラスは可変サイズの整数配列を必要としないようではないので、これらの2つのオプションのいずれかがこの場合に必要なものであるとは思われません。あなたは何か確信してますか?

template <unsigned NumDimensions> 
class Coordinate<N> { 
    std::array<int, NumDimensions> a; 
    // etc. etc. 
} 

はありませんか?

std::arrayクラス自体が本当に標準ライブラリのほとんどのように、デバイスのコードで使用することはできません。しかし、あなたは簡単にclone std::arrayし、ホストとデバイス側の両方にごcuda::arrayクラスを使用することができます。)

何らかの理由で動的なメモリの割り当てが必要な場合でも、何度も使用されるようなクラスを持つことはお勧めできません。いくつかの事前に割り当てられたバッファの使用を検討し、Coordinateがオフセットを進めるようにしてください(これはスレッドの安全性のための同期化やバッファのスレッドローカル化を必要とします)。

+1

実際にデバイスコードに 'std :: array'エンティティを使ってみましたか?あなたが見せているものを試したので、それを働かせることはできません。 –

+0

@RobertCrovella:ああ、はい、実際にはうまくいかず、OPはデバイスに何か他のものを渡す必要があります。編集を参照 – einpoklum

関連する問題