2016-08-01 89 views
-2

Wie man Vektor zu Struktur in C++ setzt (msvc 2008).C++ put Vektor zu Struktur ohne Kopie

Zum Beispiel ...

Ich habe Header-Datei .hh:

template <typename dtype> struct c_Cudamat_Struct1 { 
    thrust::device_vector<dtype> deviceVector; 
    dtype * dataHost; 
    dtype * dataDevice; 
    int onDevice; 
    int onHost; 
    (void *) shape; 
    int size; 
    int isTrans; // 0 or 1 
    int ownsData; 
    int itemsize; 

}; 

template <typename dtype> int thrust_copy_to_device(c_Cudamat_Struct1<dtype> * mat); 
template int thrust_copy_to_device<double>(c_Cudamat_Struct1<double> * mat); 
template int thrust_copy_to_device<float>(c_Cudamat_Struct1<float> * mat); 
template int thrust_copy_to_device<long>(c_Cudamat_Struct1<long> * mat); 
template int thrust_copy_to_device<int>(c_Cudamat_Struct1<int> * mat); 
template int thrust_copy_to_device<char>(c_Cudamat_Struct1<char> * mat); 

Und ich habe einige Haupt .cu Datei (?):

template <typename dtype> int thrust_copy_to_device(c_Cudamat_Struct1<dtype> * mat){ 

    print_memory_gpu("1. Start:::"); 

    thrust::device_vector<dtype> deviceVector(mat->dataHost, mat->dataHost + mat->size); 

    print_memory_gpu("2. Create deviceVector:::"); 

    mat->deviceVector = deviceVector; 

    print_memory_gpu("3. Put deviceVector to mat:::"); 


    mat->deviceVector=thrust_vector_fill_range<dtype>(mat->deviceVector, 1, mat->size); 

    print_memory_gpu("4. mat->deviceVector linspace:::"); 


    return 0; 
} 

Aber seine Herstellung Kopie :

  1. Start::: Free/Total GPU memory (MB): 1541/-2048
  2. Create deviceVector::: Free/Total GPU memory (MB): 1160/-2048
  3. Put deviceVector to mat::: Free/Total GPU memory (MB): 778/-2048
  4. mat->deviceVector linspace::: Free/Total GPU memory (MB): 876/-2048

EDIT 000/999

Hervorhebungen was wichtig ist (andere, die ich mit Zeigern aus "mat->dataDevice" behandelt) ...

template <typename dtype> int thrust_copy_to_device(c_Cudamat_Struct1<dtype> * mat){ 

    print_memory_gpu("1. Start:::"); 

    thrust::device_vector<dtype> deviceVector(mat->dataHost, mat->dataHost + mat->size); 

    print_memory_gpu("2. Create deviceVector:::"); 

    mat->deviceVector = deviceVector; 

    print_memory_gpu("3. Put deviceVector to mat:::"); 


    return 0; 
} 

Wie konnte ich diesen Teil ändern:

thrust::device_vector<dtype> deviceVector(mat->dataHost, mat->dataHost + mat->size); 

print_memory_gpu("2. Create deviceVector:::"); 

mat->deviceVector = deviceVector; 

zu etwas wie:

thrust::device_vector<dtype> mat->deviceVector(mat->dataHost, mat->dataHost + mat->size); 

print_memory_gpu("2. Create deviceVector:::"); 

Das Problem ist, dass Zeiger in Ordnung sind, aber ich brauche diesen Vektor immer noch und mache ihn von struct verfügbar.

Soll ich Klasse anstelle dieser Struktur mit einigen schlauen Methoden erstellen?

EDIT 002/999

Simplest Lösung scheint statt struct Schaffung Klasse zu sein:

In Header .hh Datei: (?)

template <class dtype> class C_Cudamat_Struct{ 
    private: 
     thrust::device_vector<dtype> deviceVector; 
    public: 
     C_Cudamat_Struct(); 
     dtype * dataHost; 
     dtype * dataDevice; 
     int onDevice; 
     int onHost; 
     (void *) shape; 
     int size; 
     int isTrans; // 0 or 1 
     int ownsData; 
     int itemsize; 

     int set_device_vector(); 

}; 

template class C_Cudamat_Struct<double>; 
template class C_Cudamat_Struct<float>; 
template class C_Cudamat_Struct<long>; 
template class C_Cudamat_Struct<int>; 

In Haupt-.cu Datei:

template <class dtype> int C_Cudamat_Struct<dtype>::set_device_vector(){ 
    print_memory_gpu("1. Start:::"); 

    thrust::device_vector<dtype> deviceVector(dataHost, dataHost + size); 

    print_memory_gpu("2. Create deviceVector:::"); 

    //mat->deviceVector = std::move (deviceVector); 

    print_memory_gpu("3. Put deviceVector to mat:::"); 

    deviceVector=thrust_vector_fill_range<dtype>(deviceVector, 1, size); 

    print_memory_gpu("4. mat->deviceVector linspace:::"); 

    return 0; 

} 

template <class dtype> C_Cudamat_Struct<dtype>::C_Cudamat_Struct(){ 

} 
+2

Ohne den Quellcode von thrust :: device_vector zu sehen, ist es schwer zu sagen, aber möglicherweise können Sie Kopieroperationen durch Verschiebungen ersetzen: 'mat-> deviceVector = std :: move (deviceVector);' –

+0

@H. Guijt - Es wäre nett, Bit das gibt mir Fehler: Namespace "Std" hat kein Mitglied "move" –

+0

Es ist in Sie könnten jedoch versucht haben, es für sich selbst zu googlen. –

Antwort

1

Die kurze Antwort ist: der C++ Compiler wird es nicht für Sie tun, Sie müssen es selbst tun. Wenn Sie keine Kopie erstellen möchten, speichern Sie in Ihrer Struktur eine std::shared_ptr oder vielleicht std::unique_ptr an den Vektor.

Alternativ konstruieren, um die ersten struct, reserve() verwenden, um die erwartete Anzahl von Elementen in den struct zu reservieren ist Vektor, dann wird die struct bevöl 's Vektor direkt. Sie können einen Vektor nicht zuerst als separates Objekt konstruieren und dann irgendwo kopieren, ohne eine Kopie zu erstellen.

Sieht aus wie Sie mehrere Kopien dieses Vektors passiert haben:

mat->deviceVector=thrust_vector_fill_range<dtype>(mat->deviceVector, 1, mat->size); 

Ich vermute, dass thrust_vector_fill_range() nehmen nicht seine Parameter Bezug genommen wird, sondern von Wert. Also, das wird eine Kopie des gesamten Vektors für den Funktionsparameter machen.Dann wird der zurückgegebene Vektor erneut kopiert. Richtig, der zurückgegebene Vektor wird unmittelbar danach zerstört, aber Ihr Compiler ist zu alt, um die Verschiebungssemantik zu unterstützen, also muss dies auf die altmodische Art geschehen.

Zusammenfassend, wenn Sie nicht unnötige Kopien Ihres Vektors machen wollen, schreiben Sie den Code richtig, das tut es nicht. Instanziieren Sie keine separate Kopie des Vektors, nur um ihn in die Struktur zu kopieren. resize() oder reserve() und befüllen Sie den Vektor der Struktur und übergeben Sie ihn dann immer als Referenz.

+0

Diese Antwort enthält sehr gute allgemeine Hinweise.Allerdings werden einige Details in diesem speziellen Problem nicht funktionieren, da die fragliche deviceVector-Klasse eigentlich eine Container-Klasse ist, die Speicher auf einer GPU einkapselt und es gibt einige Einschränkungen in Bezug darauf, was kann oder kann nicht mit dieser bestimmten Klasse im Vergleich zu 'std :: vector' gemacht werden – talonmies