在多个 GPU 上运行 MATLAB 函数
此示例显示如何在多个 GPU 上并行运行 MATLAB® 代码,首先在本地机器上,然后扩展到集群。作为一个示例问题,该示例使用了逻辑斯蒂映射,即一个仿真人口增长的方程。
MATLAB 中越来越多的功能提供自动并行支持,包括多 GPU 支持,而无需任何额外的编码。有关详细信息,请参阅使用自动并行支持运行 MATLAB 函数。例如,trainnet
(Deep Learning Toolbox)函数为训练神经网络提供多 GPU 支持。有关详细信息,请参阅Scale Up Deep Learning in Parallel, on GPUs, and in the Cloud (Deep Learning Toolbox)。
使用单个 GPU
要在单个 GPU 上运行计算,请使用 gpuArray
对象作为支持 GPU 的 MATLAB 函数的输入。要了解有关支持 GPU 的函数的更多信息,请参阅 在 GPU 上运行 MATLAB 函数。
创建定义增长率 r
和人口 x
的 GPU 数组。有关创建 gpuArray
对象的更多信息,请参阅 在 GPU 上建立数组。
N = 1000;
r = gpuArray.linspace(0,4,N);
x = rand(1,N,"gpuArray");
使用简单的算法来迭代逻辑图。由于该算法在 gpuArray
输入数据上使用支持 GPU 的运算符,因此计算在 GPU 上运行。
numIterations = 1000; for n=1:numIterations x = r.*x.*(1-x); end
计算完成后,绘制增长率与人口的关系图。
plot(r,x,'.');
如果您需要更高的性能,GPU 数组支持多种选项。有关列表,请参阅gpuArray
函数页面。例如,本例中的算法仅对 GPU 数组执行逐元素操作,因此您可以使用 arrayfun
函数为 GPU 预编译它们。
使用 parfor
的多个 GPU
您可以使用 parfor
-loops 在并行工作进程之间分配 for
-loop 迭代。如果您的计算使用支持 GPU 的函数,那么计算将在工作进程的 GPU 上运行。例如,如果您使用蒙特卡洛方法随机仿真种群的进化,则使用 parfor
循环并行使用多个 GPU 进行仿真计算。
使用 parpool
创建一个并行池,其工作进程数量与可用的 GPU 数量一样多。要确定可用的 GPU 数量,请使用 gpuDeviceCount
函数。默认情况下,MATLAB 为每个工作进程分配不同的 GPU 以获得最佳性能。有关在并行池中选择 GPU 的更多信息,请参阅 在并行池中使用多个 GPU。
numGPUs = gpuDeviceCount("available");
parpool(numGPUs);
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to the parallel pool (number of workers: 2).
定义仿真的次数,并在 GPU 中创建一个数组来存储每次仿真的人口向量。
numSimulations = 100;
X = zeros(numSimulations,N,"gpuArray");
使用 parfor
循环将仿真分发给池中的工作进程。循环内的代码为初始种群创建一个随机的 gpuArray
,并在其上迭代逻辑映射。由于代码在 gpuArray
输入数据上使用支持 GPU 的运算符,因此计算会自动在工作进程的 GPU 上运行。
parfor i = 1:numSimulations X(i,:) = rand(1,N,"gpuArray"); for n=1:numIterations X(i,:) = r.*X(i,:).*(1-X(i,:)); end end
计算完成后,绘制所有仿真的结果。每种颜色代表不同的仿真。
figure
plot(r,X,'.');
使用默认首选项,parpool
启动一个并行进程工作进程。在进程工作进程上并行运行代码通常会导致数据被复制到每个工作进程,这在使用 GPU 数组时会使用大量 GPU 内存。相比之下,线程工作进程可以共享内存。为了减少内存使用量并降低数据传输成本,请通过调用 parpool("Threads")
使用并行并行工作进程池。线程工作进程仅支持进程工作进程可用的部分函数。有关详细信息,请参阅在基于线程和基于进程的环境之间进行选择。
如果您需要更好地控制计算,可以使用更高级的并行功能。例如,您可以使用 parallel.pool.DataQueue
在计算期间从工作进程发送数据。有关示例,请参阅 使用 parfor 进行参数扫描时的绘图。
如果您想要生成一组可重现的随机数,您可以控制工作进程 GPU 上的随机数生成。有关详细信息,请参阅GPU 上的随机数流。
使用 parfeval
异步使用多个 GPU
您可以使用 parfeval
在并行池工作进程上异步运行计算。如果您的计算使用支持 GPU 的函数,那么计算将在工作进程的 GPU 上运行。举例来说,您可以在多个 GPU 上异步运行蒙特卡洛仿真。
要在工作进程完成计算后保存计算结果,请使用未来对象。为每个仿真的结果预先分配一个未来对象数组。
f(numSimulations) = parallel.FevalFuture;
要使用 parfeval
运行计算,必须将它们放在函数内部。例如,myParallelFcn
包含单个仿真的代码。
type myParallelFcn
function x = myParallelFcn(r) N = 1000; x = gpuArray.rand(1,N); numIterations = 1000; for n=1:numIterations x = r.*x.*(1-x); end end
使用 for
循环来循环仿真,并使用 parfeval
在并行池中的工作进程上异步运行它们。myParallelFcn
在 gpuArray
输入数据上使用支持 GPU 的函数,因此它们在工作进程的 GPU 上运行。因为 parfeval
异步执行计算,所以它不会阻塞 MATLAB,并且您可以在计算发生时继续工作。
for i=1:numSimulations f(i) = parfeval(@myParallelFcn,1,r); end
为了在 parfeval
的结果准备就绪时收集它们,您可以在未来对象上使用fetchOutputs
或fetchNext
。另外,您可以使用 afterEach
或 afterAll
在结果准备就绪时自动调用函数。例如,为了在每个仿真完成后立即绘制其结果,请在未来对象上使用 afterEach
。每种颜色代表不同的仿真。
figure hold on afterEach(f,@(x) plot(r,x,'.'),0);
在集群中使用多个 GPU
如果您可以访问具有多个 GPU 的集群,那么您就可以扩大计算规模。使用parpool
函数在集群上启动并行池。当您这样做时,并行功能(例如 parfor
循环或 parfeval
)将在集群工作进程上运行。如果您的计算在 gpuArray
输入数据上使用支持 GPU 的函数,那么这些函数将在集群工作进程的 GPU 上运行。请注意,集群功能仅在基于进程的环境中受支持。有关如何在集群中的远程 GPU 上运行代码的示例,请参阅 使用远程 GPU。要了解有关在集群上运行并行功能的更多信息,请参阅从桌面扩展到集群。
对快速多节点 GPU 通信的高级支持
MATLAB® 中的某些多 GPU 功能(包括 trainnet
函数)针对通过快速互连直接通信进行了优化,以提高性能。
如果您有适当的硬件连接,那么多个 GPU 之间的数据传输将使用快速点对点通信,包括 NVLink(如果可用)。
如果您正在使用机器间快速互连(例如 Infiniband)或不同机器上的 GPU 间快速互连(例如 GPUDirect RDMA)的 Linux 计算集群,则您可能能够利用 MATLAB 中的快速多节点支持。通过将环境变量 PARALLEL_SERVER_FAST_MULTINODE_GPU_COMMUNICATION
设置为 1
来对池中的所有工作进程启用此支持。在集群配置文件管理器中设置此环境变量。
此功能是用于 GPU 通信的 NVIDIA NCCL 库的一部分。要配置它,您必须设置其他环境变量来定义网络接口协议,尤其是 NCCL_SOCKET_IFNAME
。有关更多信息,请参阅 NCCL 文档,特别是 NCCL 环境变量部分。
另请参阅
gpuArray
| gpuDevice
| parpool
| parfor
| parfeval
| fetchOutputs
| afterEach
相关示例
- 在 GPU 上运行 MATLAB 函数
- 使用远程 GPU
- 从桌面扩展到集群
- Scale Up Deep Learning in Parallel, on GPUs, and in the Cloud (Deep Learning Toolbox)