coder.gpu.kernel

Прагма, которая отображает for-циклы к ядрам графический процессор

Описание

coder.gpu.kernel() - это прагма уровня цикла, которую необходимо поместить непосредственно перед циклом for. Он генерирует ядро с размерностями, вычисленными из параметров цикла.

Примечание

coder.gpu.kernel pragma переопределяет все проверки анализа параллельных циклов, которые выполняет программное обеспечение. Использовать coder.gpu.kernelfun сначала перед использованием более продвинутой функциональности coder.gpu.kernel прагма.

coder.gpu.kernel(B,T) - это прагма уровня цикла, которую необходимо поместить непосредственно перед циклом for. Он генерирует ядро с размерностями, заданными B и T. B[Bx,By,1] - массив, который определяет количество блоков в сетке по размерностям x и y (z не используется). T[Tx,Ty,Tz] - массив, который определяет количество резьб в блоке по размерностям x, y, и z.

Значение -1 для B и T указывает, что GPU Coder™ должны автоматически выводить размерности сетки и блоков. coder.gpu.kernel pragma генерирует ошибки для недопустимых размерностей сетки и блоков.

пример

coder.gpu.kernel(B,T,M,name) ожидает того же B и T аргументы. Можно задать необязательные аргументы M и name. M - положительное целое число, задающее минимальное количество блоков на потоковый многопроцессор. Иногда, увеличение M может уменьшить использование регистров в ядре и улучшить заполнение ядра. Значение -1 для M указывает, что GPU Coder должны использовать значение по умолчанию 1. name - символьный массив, который позволяет настраивать имя сгенерированного ядра.

Установка прагмы ядра переопределяет все проверки анализа параллельных циклов. Это переопределение позволяет параллелизировать циклы в ситуациях, когда анализ параллельного цикла не может доказать, что все итерации независимы друг от друга. Во-первых, убедитесь, что цикл безопасен для параллелизации.

Эта функция является функцией генерации кода. Это не влияет на MATLAB®.

Примеры

свернуть все

В этом примере показано, как использовать kernel pragma в функции и сгенерировать CUDA® код.

В одном файле запишите функцию точки входа scalars который принимает два векторных входов x,y размера 1x4096 и один скалярный вход scale. Функция имеет два for- циклы различных длин итерации, один для сложения векторов и один для нахождения совокупной суммы. Поместите coder.gpu.kernel(1,1024) прагма вне первого цикла. Эта прагма создает ядро с одним блоком, имеющим 1024 потока. Поместите coder.gpu.kernel(8,512,512,'reduction') прагма вне второго цикла. Эта прагма создает ядро с восемью блоками, имеющих 512 потоков на блок. Ядро, созданное для этого блока, называется сокращением.

function [vout, sout1] = scalars(x,y,scale)
    sout1 = 0;
    vout = coder.nullcopy(zeros(size(x)));
    
    coder.gpu.kernel(1,1024);
    for i=1:1024
        vout(i) = x(i) + y(i);
    end
    
    coder.gpu.kernel(8,512,512,'reduction');
    for i=1:4096
        sout1 = (x(i)*scale) + sout1;    
    end
end

Используйте codegen функция для генерации функции MEX CUDA.

codegen -config coder.gpuConfig('mex')...
 -args {ones(1,4096,'double'),ones(1,4096,'double'),coder.typeof(0)}...
 -report scalars

GPU Coder создает два ядра: scalars_kernel1 для сложения и scalarsreduction векторов ядро для совокупной суммы. Для инициализации не требуется ядро sout1=0.

  cudaMemcpy(gpu_y, y, 32768U, cudaMemcpyHostToDevice);
  cudaMemcpy(gpu_x, x, 32768U, cudaMemcpyHostToDevice);  
  scalars_kernel1<<<dim3(1U, 1U, 1U), dim3(1024U, 1U, 1U)>>>(gpu_y, gpu_x, gpu_vout);
  cudaMemcpy(gpu_sout1, sout1, 8U, cudaMemcpyHostToDevice);
  scalarsreduction<<<dim3(8U, 1U, 1U), dim3(512U, 1U, 1U>>>(scale, gpu_x, gpu_sout1);
  cudaMemcpy(vout, gpu_vout, 32768U, cudaMemcpyDeviceToHost);
  cudaMemcpy(sout1, gpu_sout1, 8U, cudaMemcpyDeviceToHost);

scalars_kernel1 имеет один блок с 1024 потоками на блок, по одному для добавления каждого элемента. scalarsreduction ядро имеет восемь блоков с 512 потоками на блок, в результате чего в общей сложности 4096 потоков.

Можно использовать переменные или выражения при определении размерностей ядра. Для примера можно переписать scalars функция точки входа таким образом, чтобы размерности сетки и блоков задавались во время компиляции.

function [vout, sout1] = scalars(x,y,scale, a, b)
    sout1 = 0;
    vout = zeros(size(x));
    
    coder.gpu.kernel(1,1024);
    for i=1:1024
        vout(i) = x(i) + y(i);
    end
    
    coder.gpu.kernel([a,a*b,1], [a*b, 1, 1], 'reduction');
    for i=1:length(x)
        sout1 = (x(i)*scale) + sout1;    
    end
end

Используйте codegen функция для генерации функции MEX CUDA.

codegen -config coder.gpuConfig('mex')...
 -args {ones(1,4096,'double'),ones(1,4096,'double'),20,8,4}...
 -report scalars
Введенный в R2017b