Javier Luis Lopez Ответов: 1

С++ампер против тяги против технологии OpenCL


Я программирую в графических процессорах с использованием OpenCL но я был бы счастлив с более простой системой для распараллеливания программы

Что из них подразумевает меньшее количество кода, который нужно изменить, чтобы ввести в GPU?
C++ amp и Trust позволяют последовательно запускать несколько функций внутри графического процессора, прежде чем возвращать результаты?

Что я уже пробовал:

Я сделал код с использованием OpenCL, но много работы должно быть сделано добавлено к распараллеливанию алгоритма, который является подготовкой системы, обработкой буфера, передачей данных ...

1 Ответов

Рейтинг:
0

tugrulGtx

but a lot of work must be done added to the parallelizing the algorithm that is the system preparision, buffer ctreation, data transfers


Если вы переписываете целые этапы OpenCL для каждой новой работы по программированию, то вам нужно сократить часть написания с помощью ООП, например, создать объект для выполнения не всех, а специализированных частей OpenCL для вас в рамках правил стиля RAII, чтобы то, что вы пишете 1 лайнер, было равно 10 строкам OpenCL API, и вам не нужно было запоминать, в каком порядке будут выполняться операции "высвобождения ресурсов".

Если вы не хотите заново изобретать свое собственное колесо и если вы согласны с задержкой бюрократии для исправления ошибок и интеграции функций, то есть и другие колеса.

Sycl:

std::vector h_a(LENGTH);             // a vector
  std::vector h_b(LENGTH);             // b vector
  std::vector h_c(LENGTH);             // c vector
  std::vector h_r(LENGTH, 0xdeadbeef); // d vector (result)
  // Fill vectors a and b with random float values
  int count = LENGTH;
  for (int i = 0; i < count; i++) {
    h_a[i] = rand() / (float)RAND_MAX;
    h_b[i] = rand() / (float)RAND_MAX;
    h_c[i] = rand() / (float)RAND_MAX;
  }
  {
    // Device buffers
    buffer d_a(h_a);
    buffer d_b(h_b);
    buffer d_c(h_c);
    buffer d_r(h_d);
    queue myQueue;
    command_group(myQueue, [&]()
    {
      // Data accessors
     auto a = d_a.get_access<access::read>();
     auto b = d_b.get_access<access::read>();
     auto c = d_c.get_access<access::read>();
     auto r = d_r.get_access<access::write>(); 
      // Kernel
      parallel_for(count, kernel_functor([ = ](id<> item) {
        int i = item.get_global(0);
        r[i] = a[i] + b[i] + c[i];
      }));
    });
  }


Arrayfire:

// Select a device and display arrayfire info
int device = argc > 1 ? atoi(argv[1]) : 0;
af::setDevice(device);
af::info();
printf("Create a 5-by-3 matrix of random floats on the GPU\n");
array A = randu(5,3, f32);
af_print(A);
printf("Element-wise arithmetic\n");
array B = sin(A) + 1.5;
af_print(B);
printf("Negate the first three elements of second column\n");
B(seq(0, 2), 1) = B(seq(0, 2), 1) * -1;
af_print(B);
printf("Fourier transform the result\n");
array C = fft(B);
af_print(C);
printf("Grab last row\n");
array c = C.row(end);
af_print(c);
printf("Scan Test\n");
dim4 dims(16, 4, 1, 1);
array r = constant(2, dims);
af_print(r);
printf("Scan\n");
array S = af::scan(r, 0, AF_BINARY_MUL);
af_print(S);
printf("Create 2-by-3 matrix from host data\n");
float d[] = { 1, 2, 3, 4, 5, 6 };
array D(2, 3, d, afHost);
af_print(D);
printf("Copy last column onto first\n");
D.col(0) = D.col(end);
af_print(D);
// Sort A
printf("Sort A and print sorted array and corresponding indices\n");
array vals, inds;
sort(vals, inds, A);
af_print(vals);
af_print(inds);


CUDA имеет более простой вход, чем OpenCL с его runtime API. Если вы согласны с тем, чтобы быть восстановленным к оборудованию Nvidia, то взгляните на это:

#include <stdio.h>

__global__
void saxpy(int n, float a, float *x, float *y)
{
  int i = blockIdx.x*blockDim.x + threadIdx.x;
  if (i < n) y[i] = a*x[i] + y[i];
}

int main(void)
{
  int N = 1<<20;
  float *x, *y, *d_x, *d_y;
  x = (float*)malloc(N*sizeof(float));
  y = (float*)malloc(N*sizeof(float));

  cudaMalloc(&d_x, N*sizeof(float)); 
  cudaMalloc(&d_y, N*sizeof(float));

  for (int i = 0; i < N; i++) {
    x[i] = 1.0f;
    y[i] = 2.0f;
  }

  cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);
  cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);

  // Perform SAXPY on 1M elements
  saxpy<<<(N+255)/256, 256>>>(N, 2.0f, d_x, d_y);

  cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);

  float maxError = 0.0f;
  for (int i = 0; i < N; i++)
    maxError = max(maxError, abs(y[i]-4.0f));
  printf("Max error: %f\n", maxError);

  cudaFree(d_x);
  cudaFree(d_y);
  free(x);
  free(y);
}


но если вы предпочитаете драйвер-API CUDA, то это будет так же сложно, как OpenCL, как кривая обучения. Но, конечно, при достаточной инкапсуляции вы можете создать свои собственные алгоритмы 1-liner для сортировки, отображения и вычисления вещей. Кроме того, CUDA имеет множество инструментов, помогающих разработчикам исправлять ошибки, оптимизировать и вычислять (так что вам, возможно, не придется изобретать БПФ для себя, а непосредственно использовать соответствующий инструмент в платформе CUDA).