主要内容

图形处理器上的模板处理

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

《Game of Life》是一个零玩家细胞自动机由一系列细胞组成的游戏(人口)在矩形网格中(宇宙).细胞按离散时间步进化,称为几代人。应用于细胞的一组数学规则及其邻居控制他们的生命,死亡和再现。这种“生命游戏”实现基于电子书中提供的示例Matlab的实验由克里夫硅藻土。实施遵循以下规则:

  • 单元格按二维网格排列。

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

  • 任何一个具有恰好三个现场邻居的细胞都在下一步来到生命。

  • 一个带有恰好两个现场邻居的活细胞在下一步中保持活力。

  • 所有其他细胞(包括具有超过三个邻居的细胞)在下一步中死亡,或者保持空。

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

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

第三方的先决条件

要求

本例生成CUDA MEX,并具有以下第三方需求。

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

可选的

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

验证GPU环境

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

envCfg = coder.gpuEnvConfig (“主机”);Envcf​​g.basicCodegen = 1;Envcf​​g.quiet = 1;Coder.CheckGpuInstall(Envcf​​g);

生成随机初始群体

因为游戏是零玩家,所以游戏的发展取决于它的初始状态。对于本例,在一个二维网格上创建了一个初始的细胞群,其中大约25%的位置是活的。

gridsize = 500;numgenerations = 100;initialGrid =(RAND(GridSize,Gridsize)> .75);%绘制初始网格ImagesC(初始奖金);Colormap ([1 1 1;0 0.5 0]);标题(“初始网格”);

玩生活的游戏

gameoflife_orig.m功能是完全矢量化的“生命游戏”的实现。该函数在每个生成的一次通行证中更新网格上的所有单元格。

类型gameoflife_orig
%% MATLAB矢量化实现函数grid = gameoflife_origin (initialGrid) % Copyright 2016-2019 The MathWorks, Inc. numGenerations = 100;网格= initialGrid;[gridSize ~] =大小(initialGrid);%循环每一代更新网格并显示它。for generation = 1:numGenerations grid = updateGrid(grid, gridSize);显示亮度图像(网格);Colormap ([1 1 1;0 0.5 0]);title(['Grid at Iteration ',num2str(generation)]);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函数使用gpucoder.stildkernel.pragma以在每个单元格周围计算3×3区域。模板内核的GPU编码器™实现计算每个线程中网格的一个元素,并使用共享存储器来改善内存带宽和数据局部。

类型gameoflife_stencil.
function grid = gameoflife_stencil(initialGrid) %#codegen % Copyright 2016-2019 The MathWorks, Inc. numGenerations = 100;网格= initialGrid;%循环每代更新网格。for generation = 1:numGenerations grid = gpucoder. for generation = 1:numGenerationsstencilKernel(@updateElem, grid, [3,3], 'same');X = updateElem(window) neighbors = window(1,1) + window(1,2) + window(1,3)…+ window(2,1) + window(2,3)…+ window(3,1) + window(3,2) + window(3,3);X = (window(2,2) & (neighbors == 2))) | (neighbors == 3);结束

为该功能生成CUDA MEX

要生成CUDA MEXgameoflife_stencil.函数,创建图形处理器代码配置对象,然后使用Codegen.命令。

cfg = coder.gpuconfig('mex');evalc ('codegen -config cfg -args {itialgrid} gameoflife_stencil');

运行mex函数

运行生成的gameoflife_stcencil_mex.随着随机初始人口。

gridgpu = gameoflife_stcence_mex(initialGrid);%在100代之后绘制网格ImagesC(GridGPU);Colormap ([1 1 1;0 0.5 0]);标题(“最终网格- CUDA MEX”);

也可以看看

职能

对象

相关的话题