主要内容

图形处理器上的模板处理

这个例子展示了如何通过实现John H. Conway的“Game of Life”来生成模板类型操作的CUDA®内核。

“生命游戏”是一个零玩家的游戏细胞自动机由细胞集合组成的游戏(人口)的矩形网格(宇宙).细胞以离散的时间步骤进化,称为一代又一代.应用于细胞及其邻近细胞的一组数学规则控制着它们的生、死和繁殖。这个“生命游戏”的实现是基于电子书中提供的例子MATLAB实验Cleve Moler著。实现遵循以下规则:

  • 单元格排列在二维网格中。

  • 在每一步,每个细胞的八个最近邻居的活力决定了它的命运。

  • 任何细胞到底三个邻居来生活在下一步。

  • 一个有两个活邻居的活细胞在下一步仍然是活的。

  • 所有其他单元格(包括那些有三个以上邻居的单元格)在下一步死亡或保持空。

下面是一些如何更新单元格的示例。

许多数组操作可以表示为钢网操作,其中输出数组的每个元素都依赖于输入数组的一个小区域。本例中的模板是每个单元格周围的3 × 3区域。有限差分、卷积、中值滤波和有限元方法是模板处理可以执行的其他操作的例子。

第三方的先决条件

要求

本例生成CUDA MEX,第三方需求如下。

  • CUDA支持NVIDIA®GPU和兼容的驱动程序。

可选

对于非mex构建,例如静态、动态库或可执行文件,此示例具有以下附加要求。

检查GPU环境

要验证运行此示例所需的编译器和库是否已正确设置,请使用coder.checkGpuInstall函数。

envCfg = code . gpuenvconfig (“主机”);envCfg。BasicCodegen = 1;envCfg。安静= 1;coder.checkGpuInstall (envCfg);

生成一个随机的初始人口

因为博弈是零玩家的,所以博弈的演化是由其初始状态决定的。对于本例,在二维网格上创建初始细胞群,其中约25%的位置是活动的。

gridSize = 500;numGenerations = 100;initialGrid = (rand(gridSize,gridSize) > .75);绘制初始网格显示亮度图像(initialGrid);Colormap ([1 1 1;0 0.5 0]);标题(“初始网格”);

玩生命的游戏

gameoflife_orig.m函数是“生命游戏”的完全向量化实现。该函数在每一代的一次传递中更新网格上的所有单元格。

类型gameoflife_orig
MATLAB向量化实现函数grid = gameoflife_orig(initialGrid) %版权所有2016-2019 The MathWorks, Inc. numGenerations = 100;grid = initialGrid;[gridSize,~] = size(initialGrid);遍历每一代更新网格并显示它。for generation = 1:numGenerations grid = updateGrid(grid, gridSize);显示亮度图像(网格);Colormap ([1 1 1;0 0.5 0]);title(['网格在迭代',num2str(生成)]);drawnow;索引向量将居中索引增加或减少1%,从而访问左、右、上、下的邻居。 p = [1 1:N-1]; q = [2:N N]; % Count how many of the eight neighbors are alive. neighbors = X(:,p) + X(:,q) + X(p,:) + X(q,:) + ... X(p,p) + X(q,q) + X(p,q) + X(q,p); % A live cell with two live neighbors, or any cell with % three live neighbors, is alive at the next step. X = (X & (neighbors == 2)) | (neighbors == 3); end end

调用来玩游戏gameoflife_orig具有初始总体的函数。游戏迭代100代,并显示每一代的人口。

gameoflife_orig (initialGrid);

转换游戏的生命GPU代码生成

看一下计算updateGrid函数时,很明显相同的操作分别应用于每个网格位置。然而,每个单元格必须知道它的八个邻居。修改后的gameoflife_stencil.m函数使用stencilfunPragma来计算每个单元格周围的3 × 3区域。模板内核的GPU Coder™实现在每个线程中计算网格的一个元素,并使用共享内存来提高内存带宽和数据局部性。

类型gameoflife_stencil
Copyright 2016-2019 The MathWorks, Inc. numGenerations = 100;grid = initialGrid;遍历每一代更新网格。for generation = 1:numGenerations grid = stencilfun(@updateElem, grid, [3,3], Shape='same');函数X = updateElem(window)邻居= window(1,1) + window(1,2) + window(1,3)…+ window(2,1) + window(2,3)…+窗口(3,1)+窗口(3,2)+窗口(3,3);X = (window(2,2) & (neighbors == 2)) | (neighbors == 3);结束

为函数生成CUDA MEX

生成CUDA MEXgameoflife_stencil函数,创建一个GPU代码配置对象,然后使用codegen命令。

cfg = code . gpuconfig (墨西哥人的);codegen配置cfgarg游戏{initialGrid}gameoflife_stencil
代码生成成功。

运行MEX命令功能

运行生成的gameoflife_stencil_mex初始总体是随机的。

gridGPU = gameoflife_stencil_mex(initialGrid);在100代之后绘制网格显示亮度图像(gridGPU);Colormap ([1 1 1;0 0.5 0]);标题(“最终网格- CUDA MEX”);

另请参阅

功能

对象

相关的话题