Я пытаюсь оптимизировать мой код путем реализации циклов для потоков в графическом процессоре. Я пытаюсь устранить два цикла for, используя thrust :: transform. Код на C ++ выглядит так:
ka_index = 0;
for (int i = 0; i < N_gene; i++)
{
for (int j = 0; j < n_ka_d[i]; j++ )
{
co0 = get_coeff0(ka_vec_d[ka_index]);
act[i] += (co0*ka_val_d[ka_index]);
ka_index++;
}
act[i] = pow(act[i],n);
}
Я оцениваю коэффициенты для обыкновенного дифференциального уравнения (ОДУ) в вышеуказанных циклах
и перенесли все данные на устройство с помощью тяги. Рассмотрим случай, когда число генов представлено N_gene. Цикл для цикла должен запускаться N_gene несколько раз. Второй цикл for ограничен числом активаторов (других дружественных генов в генофонде) каждого гена. Каждый ген имеет ряд активаторов (дружественных генов, присутствие которых увеличивает концентрацию гена i), представленных элементами вектора n_ka. Значение n_ka [i] может варьироваться от 0 до N_gene — 1. ka_val представляет меру активации для каждого активатора ka. ka_vec_d имеет индекс гена, который активирует ген i.
Я пытаюсь представить эти циклы с помощью итераторов, но не могу этого сделать. Я знаком с использованием thrust :: for_each (thrust :: make_zip_iterator (thrust :: make_tuple)) для одиночного цикла for, но с трудом придумал способ реализации двух циклов for с использованием counting_iterator или итераторов преобразования. Будем благодарны за любые указатели или помощь в преобразовании этих двух в циклы. Спасибо за ваше время!
Это похоже на проблему уменьшения. Я думаю, что вы можете использовать thrust::transform
с итераторами zip и thrust::reduce_by_key
, Эскиз этого решения:
// generate indices
std::vector< int > hindices;
for( size_t i=0 ; i<N_gene ; ++i )
for( size_t j=0 ; j<n_ka_d[i] ; ++j )
hindices.push_back( i );
thrust::device_vector< int > indices = hindices;
// generate tmp
// trafo1 implements get_coeff0( get< 0 >( t ) ) * get< 1 >( t);
thrust::device_vector< double > tmp( N );
thrust::transform(
thrust::make_zip_iterator(
thrust::make_tuple( ka_vec_d.begin() , ka_val_d.begin() ) ) ,
thrust::make_zip_iterator(
thrust::make_tuple( ka_vec_d.end() , ka_val_d.end() ) ) ,
tmp.begin() , trafo1 );
// do the reduction for each ac[i]
thrust::device_vector< int > indices_out( N );
thrust::reduce_by_key( indices.begin() , indices.end() , tmp.begin() ,
ac.begin() , indices_out.begin() );
// do the pow transformation
thrust::transform( ac.begin() , ac.end() , ac.begin() , pow_trafo );
Это также может быть оптимизировано transform_iterators для уменьшения количества вызовов thrust::transform
а также thrust::recuce_by_key
,
Других решений пока нет …