Ich bin neu in CUDA und habe ein paar Probleme mit Funktoren. Ich versuche einen Schub :: Vektor von Schub :: Vektoren in einen Funktor einzugeben. Zur Zeit kann ich einen Vektor eingeben und jedem Element etwas zufügen und den modifizierten Vektor mit Hilfe von schub :: for_each zurückgeben, aber wenn ich einen Vektor in einem Funktor sortieren möchte, müsste ich den gesamten Vektor gleichzeitig eingeben können Der Funktor kann als Ganzes darauf reagieren. Gibt es eine Möglichkeit, dies zu tun?Wie erzwinge ich einen Funktor, um einen ganzen Schub zu sehen :: Vektor, so dass Sortierung möglich ist?
Der folgende Code kompiliert, aber gibt den Vektor nicht sortiert zurück.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#include <thrust/functional.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/reduce.h>
#include <thrust/transform_reduce.h>
#include <thrust/transform.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/system/cuda/execution_policy.h>
#include <thrust/tuple.h>
#include <thrust/count.h>
#include <thrust/sequence.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/for_each.h>
#include <ctime>
#include <cstdio>
#include <cassert>
using namespace std;
template<typename T>
struct sort_vector
{
__host__ __device__ thrust::device_vector<float> operator() (thrust::tuple<thrust::device_vector<float>, thrust::device_vector<float>> x)
{
thrust::device_vector<float> y = thrust::get<0>(x);
thrust::sort(y.begin(), y.end());
return thrust::get<1>(x) = y;
}
};
int main() {
thrust::device_vector<float> d_fraction(5);
d_fraction[0] = 1;
d_fraction[1] = 5;
d_fraction[2] = 3;
d_fraction[3] = 2;
d_fraction[4] = 4;
cout << "original" << endl;
int f = 0;
while (f < 5){
cout << d_fraction[f] << endl;
f++;
}
cudaStream_t s1;
cudaStreamCreate(&s1);
thrust::device_vector<float> result1(5);
thrust::for_each(thrust::cuda::par.on(s1),
thrust::make_zip_iterator(thrust::make_tuple(d_fraction.begin(), result1.begin())),
thrust::make_zip_iterator(thrust::make_tuple(d_fraction.end(), result1.end())), sort_vector<thrust::device_vector<float>>());
cudaStreamSynchronize(s1);
cout << "sorted" << endl;
int d = 0;
while (d < 5){
cout << Sresult2[d] << endl;
d++;
}
cudaStreamDestroy(s1);
return 0;
}
Allerdings, wenn ich versuche, eine Referenz zu verwenden, wie
_host__ __device__ thrust::device_vector<float> operator() (thrust::tuple<thrust::device_vector<float> &, thrust::device_vector<float> &> x)
Der Code nicht mehr kompiliert.
Ist es möglich, muss ich einen Referenzzeiger für den Vektor, so dass der Funktor den gesamten Vektor sehen kann? Oder ist es möglich, dass das Problem ist, dass ich den Vektor nach Wert übergebe und es gibt eine andere Art, die ich nicht kenne, einen Vektor in einen Funktor zu übergeben?
@Robert_Crovella Das hat funktioniert, danke! Kurze Folgefrage. Ist es möglich, mehrere Zeiger auf den Funktor zu senden? Auf diese Weise könnten Sie zwei Schubvektoren zusammenfügen?Ich habe versucht, den vorhandenen Code zu ändern, aber es sendet einige Fehler wie ungültige Deklaration der Elementfunktion. – gracie
Ja, Sie können mehrere Initialisierungsparameter an einen Funktor senden. Dies ist eigentlich nur reine C++ - Aktivität (ein Funktor ist eigentlich ein C++ - Tier, nicht einzigartig für Schub), Sie müssen nur einen Konstruktor für den Funktor erstellen, der mehrere Werte akzeptiert und sie den Klassendatenmitgliedern zuweist. Ein Beispiel ist [hier] (http://stackoverflow.com/questions/35736801/making-the-number-of-key-occurances-e-qual-using-cuda-thrust/35737950#35737950), wo der 'copy_func'-Konstruktor annimmt zwei Parameter. Es gibt keinen Grund, warum Sie nicht 2 Zeiger oder beliebig viele Parameter übergeben könnten. –
Tatsächlich enthält die Antwort, die ich in meiner Antwort verlinkt habe, einen Funktor ('sort_functor') mit mehreren Parametern. Die Initialisierung wird dort anders ausgeführt, indem das funktor-Objekt instanziiert und die dynamische Parameterinitialisierung verwendet wird, anstatt einen nicht standardmäßigen Konstruktor zu verwenden. Beide Methoden sind praktikabel. –