Как получить доступ к device_vector из функтора

0

У меня возникают проблемы с созданием функтора для доступа к вектору устройства. В принципе, у меня есть два вектора устройств, которые я хотел бы использовать внутри функтора. Функтор вызывается во время for_each.

Вот мой функтор:

struct likelihood_functor
{
int N;
float* v1;
float* v2;

likelihood_functor(int _N, float* _v1, float* _v2) : N(_N),v1(_v1),v2(_v2) {}
template <typename Tuple>

__host__ __device__ void operator()(Tuple t)
{
    float A = thrust::get<0>(t);
    float rho = thrust::get<1>(t);
    float mux = thrust::get<2>(t);
    float muy = thrust::get<3>(t);
    float sigx = thrust::get<4>(t);
    float sigy = thrust::get<5>(t);

    thrust::device_ptr<float> v1_p(v1);
    thrust::device_vector<float> X(v1_p,v1_p+N);
            thrust::device_ptr<float> v2_p(v2);
    thrust::device_vector<float> Y(v2_p,v2_p+N);

    thrust::get<6>(t) = 600*logf(A)
        - 600/2*logf(sigx*sigx*sigy*sigy*(1-rho*rho))
        - thrust::reduce(X.begin(),X.end())
        - thrust::reduce(Y.begin(),Y.end())
        - 2*rho/(sigx*sigy);
}
};

И вот моя главная():

int main(void)
{

// create a 2D dataset
const int N=2500; //number of counts

thrust::device_vector<float> data_x(N);
thrust::device_vector<float> data_y(N);

thrust::counting_iterator<unsigned int> begin(0);
    thrust::transform(begin,
        begin + N,
        data_x.begin(),
        get_normal(5.f,1.f,2.f));
thrust::transform(begin,
        begin + N,
        data_y.begin(),
        get_normal(5.f,1.f,2.f));

    //
    // Some code here to initiate A_n, rho_na, mux_n etc...
    //

// apply the transformation
thrust::for_each(
    thrust::make_zip_iterator( 
      thrust::make_tuple(A_n.begin(), rho_n.begin(), mux_n.begin(),  muy_n.begin(), sigx_n.begin(),sigy_n.begin(), L.begin()) 
    ), 
    thrust::make_zip_iterator( 
      thrust::make_tuple(A_n.end(), rho_n.end(), mux_n.end(), muy_n.end(), sigx_n.end(),sigy_n.end(),L.end())
    ), 
    likelihood_functor(N,thrust::raw_pointer_cast(&(data_x[0])),thrust::raw_pointer_cast(&(data_y[0])))
    );

// print the output
for(int i=0; i<4096; i++)
{
    std::cout << "[" << i << "] : " << L[i] <<std::endl;
}

}

Код компилируется, но он не запускается. Я знаю, это потому, что в моем функторе device_vector X и Y выполняются неправильно.

Я использовал тот же код для создания X и Y в своей основной функции, и когда я это делаю, программа работает нормально (в этом случае я не называю функтором). Что отличается от внутри функтора, который заставляет что-то работать в основной программе, а не в функторе?

Есть ли другой способ делать то, что я пытаюсь сделать?

Спасибо вам за помощь!

Теги:
cuda
thrust

1 ответ

0
Лучший ответ

Алгоритмы тяги (например, преобразования, сокращения и т.д.) Не могут использоваться в коде устройства cuda.

То есть любая функция, которой предшествуют __global__ или __device__ не может использовать тягу (например, не использовать, например, thrust::reduce).

Поэтому ваш функтор не будет работать в коде устройства, так как он использует конструкции тяги (например, thrust::reduce).

Я понимаю, вы говорите, что ваш код компилируется, но я не уверен, что считаю. Если я попытаюсь объявить код thrust::device_vector внутри кода __device__, я получаю ошибки компиляции. Поскольку код, который вы здесь показали, является неполным во многих отношениях, я не могу легко продемонстрировать это с вашим кодом из-за других проблем с тем, что вы опубликовали.

  • 0
    Спасибо за ваш ответ. Я немного сбит с толку: я видел примеры функторов, вызываемых в for_each, где использовался thrust :: get, и они были функциями устройства . (именно поэтому я сделал это в своей функции: нашел это непосредственно в руководстве по быстрому старту или что-то в этом роде ...). Если я не могу использовать Thrust в функции устройства , то я не могу использовать Thrust :: Get, но я могу ... Теперь, если действительно невозможно получить доступ к моим наборам данных внутри функции устройства, что было бы хорошо обойти это? Большое спасибо.
  • 0
    Вы можете использовать thrust::get . Вы не можете использовать thrust::reduce . Функтор в тяге вызывается для каждого потока. Поэтому вы хотите изменить свой алгоритм, чтобы сделать обработку, выполняемую функтором, чем-то, что разумно делать в одном потоке. Вы, безусловно, можете изменить использование thrust::reduce в качестве простого цикла for, выполняемого одним потоком. Производительность может быть проблемой. И нигде я не сказал, что невозможно получить доступ к вашим наборам данных в функции устройства. Вы просто не можете использовать алгоритмы тяги.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню