Полагаю, вы используете этот код.
Любопытной характеристикой этого кода является то, что матрица определяется с использованием типа double
, но полученные минимумы сохраняются в векторе float
.
Если вы хотите использовать этот код как есть, в соответствии с моим тестированием, тяге (в CUDA 10 и, очевидно, также в CUDA 8) не нравится эта строка:
thrust::minimum<thrust::tuple<float, int> >()
Этот оператор используется для сравнения двух элементов, чтобы определить, какой из них меньше, и он может принимать различные типы элементов. Однако было решено, что поиск как минимум двух из этих кортежей является «неоднозначным» запросом. Частично это объясняется тем, что оператор возвращает кортеж float, int
, но ему по-разному присваивается кортеж double,int
или float,int
.
Мы можем исправить / обойти эту проблему, передав наш собственный функтор для выполнения работы, что является явным с точки зрения обработки передаваемых ему кортежей:
$ cat t373.cu
#include <iterator>
#include <algorithm>
#include <thrust/device_vector.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/reduce.h>
#include <thrust/functional.h>
#include <thrust/random.h>
using namespace thrust::placeholders;
struct my_min
{
template <typename T1, typename T2>
__host__ __device__
T2 operator()(T1 t1, T2 t2){
if (thrust::get<0>(t1) < thrust::get<0>(t2)) return t1;
return t2;
}
};
int main()
{
const int Nrows = 6;
const int Ncols = 8;
/**************************/
/* SETTING UP THE PROBLEM */
/**************************/
// --- Random uniform integer distribution between 0 and 100
thrust::default_random_engine rng;
thrust::uniform_int_distribution<int> dist(0, 20);
// --- Matrix allocation and initialization
thrust::device_vector<double> d_matrix(Nrows * Ncols);
for (size_t i = 0; i < d_matrix.size(); i++) d_matrix[i] = (double)dist(rng);
printf("\n\nMatrix\n");
for(int i = 0; i < Nrows; i++) {
std::cout << " [ ";
for(int j = 0; j < Ncols; j++)
std::cout << d_matrix[i * Ncols + j] << " ";
std::cout << "]\n";
}
/**********************************************/
/* FIND ROW MINIMA ALONG WITH THEIR LOCATIONS */
/**********************************************/
thrust::device_vector<float> d_minima(Ncols);
thrust::device_vector<int> d_indices(Ncols);
thrust::reduce_by_key(
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)) + Nrows * Ncols,
thrust::make_zip_iterator(
thrust::make_tuple(thrust::make_permutation_iterator(
d_matrix.begin(),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), ((_1 % Nrows) * Ncols + _1 / Nrows))),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 % Nrows)))),
thrust::make_discard_iterator(),
thrust::make_zip_iterator(thrust::make_tuple(d_minima.begin(), d_indices.begin())),
thrust::equal_to<int>(),
my_min()
// thrust::minimum<thrust::tuple<float, int> >()
);
printf("\n\n");
for (int i=0; i<Nrows; i++) std::cout << "Min position = " << d_indices[i] << "; Min value = " << d_minima[i] << "\n";
return 0;
}
$ nvcc -o t373 t373.cu
$ ./t373
Matrix
[ 0 1 12 18 20 3 10 8 ]
[ 5 15 1 11 12 17 12 10 ]
[ 18 20 15 20 6 8 18 13 ]
[ 18 20 3 18 19 6 19 8 ]
[ 6 10 8 16 14 11 12 1 ]
[ 12 9 12 17 10 16 1 4 ]
Min position = 0; Min value = 0
Min position = 0; Min value = 1
Min position = 1; Min value = 1
Min position = 1; Min value = 11
Min position = 2; Min value = 6
Min position = 0; Min value = 3
$
Я думаю, что лучше исправить это просто выбрать один или другой, float
или double
. Например, если мы изменим все типы float
на double
, то тяга будет счастливой, без каких-либо других изменений:
$ cat t373a.cu
#include <iterator>
#include <algorithm>
#include <thrust/device_vector.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/reduce.h>
#include <thrust/functional.h>
#include <thrust/random.h>
using namespace thrust::placeholders;
int main()
{
const int Nrows = 6;
const int Ncols = 8;
/**************************/
/* SETTING UP THE PROBLEM */
/**************************/
// --- Random uniform integer distribution between 0 and 100
thrust::default_random_engine rng;
thrust::uniform_int_distribution<int> dist(0, 20);
// --- Matrix allocation and initialization
thrust::device_vector<double> d_matrix(Nrows * Ncols);
for (size_t i = 0; i < d_matrix.size(); i++) d_matrix[i] = (double)dist(rng);
printf("\n\nMatrix\n");
for(int i = 0; i < Nrows; i++) {
std::cout << " [ ";
for(int j = 0; j < Ncols; j++)
std::cout << d_matrix[i * Ncols + j] << " ";
std::cout << "]\n";
}
/**********************************************/
/* FIND ROW MINIMA ALONG WITH THEIR LOCATIONS */
/**********************************************/
thrust::device_vector<double> d_minima(Ncols);
thrust::device_vector<int> d_indices(Ncols);
thrust::reduce_by_key(
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)) + Nrows * Ncols,
thrust::make_zip_iterator(
thrust::make_tuple(thrust::make_permutation_iterator(
d_matrix.begin(),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), ((_1 % Nrows) * Ncols + _1 / Nrows))),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 % Nrows)))),
thrust::make_discard_iterator(),
thrust::make_zip_iterator(thrust::make_tuple(d_minima.begin(), d_indices.begin())),
thrust::equal_to<int>(),
thrust::minimum<thrust::tuple<double, int> >()
);
printf("\n\n");
for (int i=0; i<Nrows; i++) std::cout << "Min position = " << d_indices[i] << "; Min value = " << d_minima[i] << "\n";
return 0;
}
$ nvcc -o t373a t373a.cu
$ ./t373a
Matrix
[ 0 1 12 18 20 3 10 8 ]
[ 5 15 1 11 12 17 12 10 ]
[ 18 20 15 20 6 8 18 13 ]
[ 18 20 3 18 19 6 19 8 ]
[ 6 10 8 16 14 11 12 1 ]
[ 12 9 12 17 10 16 1 4 ]
Min position = 0; Min value = 0
Min position = 0; Min value = 1
Min position = 1; Min value = 1
Min position = 1; Min value = 11
Min position = 2; Min value = 6
Min position = 0; Min value = 3
$
Я думаю, что последнее решение использования согласованных типов является более разумным решением.