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).