Aaaaa988

Untitled

Jun 16th, 2020
126
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <cublas_v2.h>
  3. #include <thrust/host_vector.h>
  4. #include <thrust/device_vector.h>
  5. #include <thrust/transform.h>
  6. #include <thrust/fill.h>
  7. #include <thrust/sequence.h>
  8. #define N 9000000
  9.  
  10. struct saxpyFunctor { //Бинарный оператор
  11.     const float a;
  12.     saxpyFunctor(float _a) : a(_a) {}
  13.     __host__ __device__ float operator()(float x, float y) {
  14.         return a * x + y;
  15.     }
  16. };
  17.  
  18. __global__ void cudaSaxpy(float alpha, float *x, float *y) { //Функция для вычисления Saxpy в CUDA C
  19.     int i = threadIdx.x + blockIdx.x * blockDim.x; //определяем индекс, по координате потока в блоке + координаты блока в сетке * размер блока
  20.     y[i] = alpha * x[i] + y[i]; //вычисляем Saxpy где S - float - тоесть вещественные числа, а axpy это a*x+y (ax plus y = axpy)
  21. }
  22.  
  23. void saxpy(float a, thrust::device_vector<float>& x, thrust::device_vector<float>& y) { //функция для траст библиотеки
  24.     saxpyFunctor func(a); // инициализация бинарного оператора.
  25.     thrust::transform(x.begin(), x.end(), y.begin(), y.begin(), func); // происходит трансформация, от начала вектора х и У до их конца, соглсно функции func
  26.     //происходит проход от начала x и y, где согласно БИНАРНОЙ функции SAXPY мы выводим результат в операторный вектор y, тоесть мы берем из У информацию, обсчитываем вместе с Х и кладем обратно в ту же ячейку вектора У откуда брали только что данные
  27. }
  28.  
  29. void CudaKernel(){
  30.     float elapsedTime; // затраченное время
  31.     cudaEvent_t start, stop;  // Объекты событий
  32.     float *x_d, *x_h, *y_h, *y_d; // вещественные указатели на x и y девайса и хоста
  33.     cudaEventCreate(&start); // функция создания события
  34.     cudaEventCreate(&stop);
  35.     cudaMalloc((void**)&x_d, N * sizeof(float)); //выделение глобальной памяти где x_d указатель на память в девайсе, N - размерность
  36.     cudaMalloc((void**)&y_d, N * sizeof(float));
  37.     x_h = (float*)calloc(N, sizeof(float)); //выделение памяти на хосте
  38.     y_h = (float*)calloc(N, sizeof(float));
  39.  
  40.     for(int i = 0; i < N; i++) { //заполнение векторов на хосте
  41.         x_h[i] = i;
  42.         y_h[i] = 0.87;
  43.     }
  44.  
  45.     cudaMemcpy(x_d, x_h, N * sizeof(float), cudaMemcpyHostToDevice);    // перенос вектора с хоста на девайс
  46.     cudaMemcpy(y_d, y_h, N * sizeof(float), cudaMemcpyHostToDevice);   
  47.  
  48.     cudaEventRecord(start, 0); // запускаем событие, для начала отсчета таймера
  49.     cudaSaxpy << < N / 256, 256 > >> (3.0, x_d, y_d); //Вызов ядра <<< Число блоков, число нитей в блоке>> ( аргументы функции) туда мы передаем альфу, и векторы на девайсе
  50.     cudaDeviceSynchronize(); // в теории оно тут не нужно
  51.     cudaEventRecord(stop, 0); // фиксируем событие окончания вычислений
  52.    
  53.     cudaEventSynchronize(stop); //Данная функция ожидает окончание работы всех нитей GPU и прохождение заданного event’а и только потом отдает управление вызывающей программе.
  54.     cudaEventElapsedTime(&elapsedTime, start, stop); //подсчет дельты между событиями
  55.     cudaMemcpy(y_h, y_d, N * sizeof(float), cudaMemcpyDeviceToHost); //копирование с девайса на хост
  56.     printf("CUDA Kernel Time:\n \t %f ms\n", elapsedTime);
  57.     free(x_h); //высвобождение памяти на хосте
  58.     free(y_h);
  59.     cudaFree(y_d); // высвобождение глобальной памяти на девайсе
  60.     cudaFree(x_d);
  61.     cudaEventDestroy(start);
  62.     cudaEventDestroy(stop);
  63. }
  64.  
  65. void cudaCublas(){
  66.      float elapsedTime;
  67.     cudaEvent_t start, stop;
  68.     float *cx_d, *cx_h, *cy_h, *cy_d;
  69.     cudaEventCreate(&start);
  70.     cudaEventCreate(&stop);
  71.    
  72.     cudaMallocHost((void**)&cx_h, N * sizeof(float)); //выделение pinned-памяти. особый участок памяти на ОЗУ
  73.     cudaMallocHost((void**)&cy_h, N * sizeof(float));
  74.     cudaMalloc((void**)&cx_d,  N * sizeof(float)); // выделение на девайсе глобальной памяти
  75.     cudaMalloc((void**)&cy_d,  N * sizeof(float));
  76.    
  77.     for(int i = 0; i < N; i++) { // заполнение на хосте
  78.         cx_h[i] = (float) i;
  79.         cy_h[i] = 0.87f;
  80.     }
  81.    
  82.     cublasHandle_t cublas_handle; //создание объекта  для работы с библиотекой
  83.     cublasCreate(&cublas_handle); //иницилазация работы с библиотекой
  84.    
  85.     const int num_rows = N;
  86.     const int stride = 1;
  87.    
  88.     cublasSetVector(num_rows, sizeof(float), cx_h, stride, cx_d, stride); // инициализация вектора на девайсе
  89.     cublasSetVector(num_rows, sizeof(float), cy_h, stride, cy_d, stride);
  90.    
  91.    
  92.     float alpha = 3.0f;
  93.    
  94.     cudaEventRecord(start, 0);
  95.     cublasSaxpy(cublas_handle, N, &alpha, cx_d, stride, cy_d, stride); // моя функция для высчета суммы векторов
  96.     cudaEventRecord(stop, 0);
  97.    
  98.     cudaEventSynchronize(stop); // ждем выполнения всех нитей для события завершения
  99.     cudaEventElapsedTime(&elapsedTime, start, stop);
  100.    
  101.     cublasGetVector(num_rows, sizeof(float), cy_d, stride, cy_h, stride);
  102.     printf("cuBLAS Time:\n \t %f ms\n", elapsedTime);
  103.     cublasDestroy(cublas_handle);
  104.     cudaFreeHost(cx_h);  //высвобождение pinned-памяти
  105.     cudaFreeHost(cy_h);
  106.     cudaFree(cx_d);  // высвобождение хостовой памяти
  107.     cudaFree(cy_d);
  108.     cudaEventDestroy(start);
  109.     cudaEventDestroy(stop);
  110. }
  111.  
  112.  
  113. void ThrustLib(){
  114.      float elapsedTime;
  115.     cudaEvent_t start, stop;
  116.     cudaEventCreate(&start);
  117.     cudaEventCreate(&stop);
  118.     thrust::host_vector<float> h1(N); // инициализация векторов на хосте
  119.     thrust::host_vector<float> h2(N);
  120.     thrust::sequence(h1.begin(), h1.end()); // создаем секвенцию в векторе h1 от начала до конца, с заполнением от 1 до N
  121.     thrust::fill(h2.begin(), h2.end(), 0.87); // заполнение вектора неким числом
  122.    
  123.     thrust::device_vector<float> d1 = h1; // копируем векторы хоста в векторы на девайс
  124.     thrust::device_vector<float> d2 = h2;
  125.    
  126.     cudaEventRecord(start, 0); //фиксируем событие начала
  127.     saxpy(3.0, d1, d2);
  128.     cudaEventRecord(stop, 0); // кончала
  129.    
  130.     cudaEventSynchronize(stop); // синхронизируем ждем
  131.     cudaEventElapsedTime(&elapsedTime, start, stop); // подсчитываем финальный итог
  132.    
  133.     h2 = d2; // обратное копирование
  134.     h1 = d1;
  135.    
  136.     printf("THRUST Time:\n \t %f ms\n\n", elapsedTime);
  137.     cudaEventDestroy(start);
  138.     cudaEventDestroy(stop);
  139. }
  140.  
  141.  
  142. int main() {
  143.     CudaKernel();
  144.     cudaCublas();
  145.     ThrustLib();
  146.     return 0;
  147. }
RAW Paste Data