2015-06-07 5 views
2

Я заинтересован в переносе существующего кода на использование тяги, чтобы узнать, могу ли я ускорить его на GPU с относительной легкостью.Сжатие потока с помощью тяги; лучшие практики и быстрый способ?

То, что я хочу выполнить, - операция уплотнения потока, в которой будут храниться только ненулевые элементы. У меня это в основном работает, например, в примере кода. Часть, в которой я не уверен, как бороться, имеет дело со всем дополнительным заполняющим пространством, которое находится в d_res и, таким образом, h_res, после того, как произойдет уплотнение.

В примере просто используется последовательность 0-99 со всеми четными элементами, установленными на ноль. Это всего лишь пример, и реальной проблемой будет общий разреженный массив.

Этот ответ здесь мне очень помог, хотя, когда дело доходит до считывания данных, размер как раз известно, что константа: How to quickly compact a sparse array with CUDA C?

Я подозреваю, что я могу работать вокруг этого путем подсчета числа 0-х в d_src, а затем выделяет только d_res для этого размера или делает счет после уплотнения и копирует только этот элемент. Это действительно правильный способ сделать это?

У меня есть смысл, что для этого будет какое-то легкое исправление, благодаря умному использованию итераторов или некоторой другой особенности тяги.

#include <thrust/host_vector.h> 
#include <thrust/device_vector.h> 
#include <thrust/copy.h> 

//Predicate functor 
struct is_not_zero 
{ 
    __host__ __device__ 
     bool operator()(const int x) 
    { 
     return (x != 0); 
    } 
}; 

using namespace std; 

int main(void) 
{ 
    size_t N = 100; 

    //Host Vector 
    thrust::host_vector<int> h_src(N); 

    //Fill with some zero and some nonzero data, as an example 
    for (int i = 0; i < N; i++){ 
     if (i % 2 == 0){ 
      h_src[i] = 0; 
     } 
     else{ 
      h_src[i] = i; 
     } 
    } 

    //Print out source data 
    cout << "Source:" << endl; 

    for (int i = 0; i < N; i++){ 
     cout << h_src[i] << " "; 
    } 
    cout << endl; 

    //copies to device 
    thrust::device_vector<int> d_src = h_src; 

    //Result vector 
    thrust::device_vector<int> d_res(d_src.size()); 

    //Copy non-zero elements from d_src to d_res 
    thrust::copy_if(d_src.begin(), d_src.end(), d_res.begin(), is_not_zero()); 

    //Copy back to host 
    thrust::host_vector<int> h_res(d_res.begin(), d_res.end()); 
    //thrust::host_vector<int> h_res = d_res; //Or just this? 

    //Show results 
    cout << "h_res size is " << h_res.size() << endl; 
    cout << "Result after remove:" << endl; 

    for (int i = 0; i < h_res.size(); i++){ 
     cout << h_res[i] << " "; 
    } 
    cout << endl; 

    return 0; 
} 

Кроме того, я новичок с тягой, так что, если приведенный выше код имеет какие-либо очевидные недостатки, которые идут против рекомендуемой практики использования тяги, пожалуйста, дайте мне знать.

Аналогично, скорость всегда представляет интерес. Читая некоторые из различных руководств по упорству, здесь, кажется, небольшие изменения, и там могут быть большие сберегатели скорости или расточители. Поэтому, пожалуйста, дайте мне знать, если есть умный способ ускорить это.

ответ

2

Что вы, кажется, упустили, так это то, что copy_if возвращает итератор, который указывает на конец скопированных данных из операции уплотнения потока. Таким образом, все, что требуется, это:

//copies to device 
thrust::device_vector<int> d_src = h_src; 

//Result vector 
thrust::device_vector<int> d_res(d_src.size()); 

//Copy non-zero elements from d_src to d_res 
auto result_end = thrust::copy_if(d_src.begin(), d_src.end(), d_res.begin(), is_not_zero()); 

//Copy back to host 
thrust::host_vector<int> h_res(d_res.begin(), result_end); 

Выполнение этого размеры h_res только держать НЕРАСПРОСТРАНЕНИИ нули и только копии, не входящих в нули с выхода потока уплотнения. Никаких дополнительных вычислений не требуется.

+0

Это именно то, что я искал, спасибо. Похоже, что «remove» имеет аналогичный возврат, поэтому теперь я также могу сравнить время этого подхода remove-then-sort на reverse, sort-then-remove. –

 Смежные вопросы

  • Нет связанных вопросов^_^