24 Temmuz 2020 Cuma

NVIDIA thrust Kütüphanesi

Giriş
Quick Start Guide yazısını okumak lazım. thrust CUDA ile çok kolay kullanılıyor. Şöyle yaparız.
$ nvcc -o t1254 t1254.cu
Kurulum
Bu kütüphane sadece header dosyalarından oluşuyor. Açıklaması şöyle.
Since Thrust is a template library of header files, no further installation is necessary to start using Thrust.
Sadece CUDA Toolkit kurulumu gerekli.  Açıklaması şöyle.
Installing the CUDA toolkit should be sufficient.
GPU Güç Tüketimi
GPU'lar çok fazla güç tüketirler. Açıklaması şöyle. GPU'larda çok fazla sayıda transistör bulunur
A GPU is basically a LOT of simplified CPUs in parallel. Each of them is not as capable and flexible as a real CPU, but there are thousands of them to give this massive parallel computing performance.

But this also means that it takes many billions of transistors to build a modern GPU. And for logic chips we use FETs, so with every clock cycle all the billions of gate capacitances have to be charged and discharged. This is where the large amount of power is going.
Embarrassingly Parallel İşler
Bazı işler GPU için uygun değildir. Açıklaması şöyle
GPUs work with the model SIMD (single instruction multiple data) i.e. they execute an instruction over multiple data. To give an idea: under CUDA technology when you have got an if-then-else condition the two branches are executed in sequence over the respective data.

In your question, the condition to favor a CPU suggests a MISD or MIMD model, i.e. different instruction over the same data or different data.
thrust::device_vector Sınıfı
GPU bellekteki bir alanı temsil eder. Şu satır dahil edilir.
#include <thrust/device_vector.h>
Şöyle tanımlanır.
const int dsize = 1000;
thrust::device_vector<int> dVector(dsize, 1);
thrust::host_vector Sınıfı
Ana bir alanı temsil eder. Şu satır dahil edilir.
#include <thrust/host_vector.h>
Şöyle tanımlanır.
const int hSize = 10;
thrust::host_vector<int> hVector(hSize);
thrust::copy_n metodu
Şöyle yaparız.
thrust::device_vector<int> d_r = ...;
int rsize = ...
thrust::copy_n(d_r.begin(), rsize, std::ostream_iterator<int>(std::cout, " "));
thrust::exclusive_scan metodu
Şöyle yaparız.
thrust::exclusive_scan(VAR2.begin(), VAR2.end(), VAR1.begin(), 0);
thrust::inclusive_scan_by_key metodu
Şöyle yaparız.
template <typename T>
void scan_horizontally(size_t m, size_t n, thrust::device_vector<T>& d_data)
{
    thrust::counting_iterator<size_t> indices(0);

    thrust::inclusive_scan_by_key
        (thrust::make_transform_iterator(indices, row_index(n)),
        thrust::make_transform_iterator(indices, row_index(n)) + d_data.size(),
        d_data.begin(),
        d_data.begin());
}
Girdi ve çıktı olarak şunu alırız.
Input: [0, 1, 2, 3
        4, 5, 6, 7
        8, 9, 10, 11,
        12, 13, 14, 15]

Output: [0, 1, 3, 6
        4, 9, 15, 22
        8, 17, 27, 38,
        12, 25, 39, 54]
thrust::partition_copy metodu
Şu satırı dahil ederiz.
#include <thrust/partition.h>
Önce partition işlemi için kullanılacak metod yazılır.
struct is_even {
 __host__ __device__ bool operator()(const int &x) { 
    return (x % 2) == 0;
  } 
};
Daha sonra 3 tane vector tanımlanır.
const int N = 10;
thrust::host_vector<int> hVector = ...;


thrust::device_vector<int> dVector      (hVector);//Copy
thrust::device_vector<int> dVectorEvens (N/2);
thrust::device_vector<int> dVectorOdds  (N/2);
Sonra dVector bölümlenir.
thrust::partition_copy(dVector.begin(), dVector.end(),
                       dVectorEvens.begin(), dVectorOdds.begin(), is_even());
thrust::reduce_by_key metodu
Şöyle yaparız.
thrust::reduce_by_key(
    keys_input.begin(),
    keys_input.end(),
    values_input.begin(),
    thrust::make_discard_iterator(),    values_output.begin(),
    thrust::equal_to<int>(),
    thrust::plus<int>());

thrust::transform metodu
Önce namespace dahil edilir.
using namespace thrust::placeholders;
Daha sonra algoritma çağrılır.
thrust::transform(VAR1.begin(), VAR1.end(), VAR1.begin(),  _1 += 1);

Hiç yorum yok:

Yorum Gönder