exponenta event banner

coder.gpu.kernel

Прагматика, которая отображает for-закольцовывается в ядра GPU

Описание

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 указывает на то, что Coder™ графического процессора должны автоматически выводить размеры сетки и блока. coder.gpu.kernel pragma создает ошибки для недопустимых размеров сетки и блока.

пример

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

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

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

Примеры

свернуть все

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

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

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 для создания функции CUDA MEX.

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

Кодер графического процессора создает два ядра: 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 для создания функции CUDA MEX.

codegen -config coder.gpuConfig('mex')...
 -args {ones(1,4096,'double'),ones(1,4096,'double'),20,8,4}...
 -report scalars
Представлен в R2017b