Je suis nouveau à CUDA et j'ai un peu de mal avec les foncteurs. J'essaie d'entrer un thrust :: vector of thrust :: vectors dans un foncteur. Actuellement, je peux entrer un vecteur et faire quelque chose à chaque élément et retourner le vecteur modifié en utilisant thrust :: for_each, mais si je devais trier un vecteur dans un foncteur, je devrais être capable d'entrer le vecteur entier le foncteur peut agir sur lui dans son ensemble. Y a-t-il un moyen de faire cela?Comment forcer un foncteur à voir un ensemble thrust :: vector pour que le tri soit possible?
Le code ci-dessous compile, mais ne renvoie pas le vecteur trié.
#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;
}
Cependant, lorsque je tente d'utiliser une référence telle que
_host__ __device__ thrust::device_vector<float> operator() (thrust::tuple<thrust::device_vector<float> &, thrust::device_vector<float> &> x)
Le code ne compile.
Est-il possible que je doive lancer un pointeur de référence pour le vecteur afin que le foncteur puisse voir le vecteur entier? Ou est-ce possible que le problème est que je passe le vecteur par la valeur et il y a une façon différente que je ne connais pas de passer un vecteur dans un foncteur?
@Robert_Crovella Cela a fonctionné, merci! Question de suivi rapide. Est-il possible d'envoyer plusieurs pointeurs au foncteur? De cette façon, vous pouvez ajouter deux vecteurs de poussée ensemble?J'ai essayé de modifier le code existant, mais il envoie quelques erreurs telles que la redéclaration invalide de la fonction de membre. – gracie
Oui, vous pouvez envoyer plusieurs paramètres d'initialisation à un foncteur. C'est en fait une pure activité C++ (un foncteur est en fait un animal C++, pas unique à la poussée), il vous suffit de créer un constructeur pour le foncteur qui accepte plusieurs valeurs et les affecte aux membres de données de classe. Un exemple est [ici] (http://stackoverflow.com/questions/35736801/making-the-number-of-key-occurances-equal-using-cuda-thrust/35737950#35737950) où le constructeur 'copy_func' prend deux paramètres. Il n'y a pas de raison que vous ne puissiez pas passer 2 pointeurs ou autant de paramètres que vous voulez. –
En fait, la réponse que j'ai liée dans ma réponse contient un foncteur ('sort_functor') avec plusieurs paramètres. L'initialisation y est effectuée différemment, en instanciant l'objet functor et en utilisant l'initialisation de paramètres dynamiques, plutôt qu'en utilisant un constructeur non par défaut. L'une ou l'autre méthode est réalisable. –