为什么我的matlab跑不满cpu的资源(cpu占用率低)—— matlab的并行池与parfor循环

沉睡的小灰 2024-09-03 11:05:02 阅读 65

前言

最近拿到了一台CPU服务器,准备来跑个大规模的优化问题。CPU服务器的配置是,3990x的U,传说中的线程撕裂者哈哈哈哈哈哈哈,拥有64核和128核心。咱就是说,可激动了。库库准备上来拿来跑个算法,看看我们建立的物理模型咋样。

我用的进化计算的平台是Platemo,这里安利一下Platemo,是安徽大学的田野老师主导的一个matlab编写的进化计算的平台,详情可见github链接https://github.com/BIMK/PlatEMO。虽然我一开始接触的时候觉得很抵触,因为python用多了,就会觉得matlab是什么狗屎东西哈哈哈,虽然现在还是觉得matlab没python好使,不过嘛,好用省时间就行。

在这里插入图片描述

问题

我大概所做的是呢,针对一个问题进行优化和建模。关于一个优化问题,需要计算目标函数约束,所以导致我需要进行多层循环嵌套,去进行计算,而且我还需要针对每个种群的决策变量进行计算,最终我的循环可能导致3-4层。这个时候无论我在linux还是在windows跑,我发现,我只有1-2个CPU核心跑满了,但是剩下的基本上都在不工作。我就满脸问号了,**为什么跑不满呢?**我以前用pytorch或者TensorFlow做深度学习的时候,我在GPU上跑能把GPU功耗拉到90%以上,CPU直接都是99%的占满,为什么matlab跑不满。matlab真是狗都不用啊!哈哈哈哈哈,听我说,你先别急。在我的一番查找之后,找到了资料,那就是Parallel Pool 。用system-monitor看的样子如下,看看这多么线程,都没用啊呜呜呜呜!

在这里插入图片描述

娓娓道来

matlab工具包

首先,看这篇文章的大伙,应该都是在使用matlab的人。我们都知道matlab会有很多工具包,我们首先要确保,matlab安装好了Parallel Computing Toolbox这个工具包。我们可以如下去检查,如果成功安装会是这样的界面在Home-> Environment->Parallel能看到并行池的设置。

在这里插入图片描述

在左下角和中上部分都能看到这样的样子。如果你没有的话,就是没有安装相关的包,你需要先安装对应的工具包才能使用。在这里不过多赘述如何安装对应的工具包了。

原理简述

正常来说,我们所编写的matlab程序是一个单线程程序,这一点是毋庸置疑的。在python如果你想,你也需要开多个线程,来避免程序运行过慢。以我的经验来说,我一般是自己设计,想要在不同的线程干不同的事情。如果是对AI相关了解的朋友,应该也见过那种选项修改,比如说修改num_worker数量这样的问题。其实这些操作都是多线程,并行计算,只不过,在python或者其他的一些包里面,提前给我们封装好,这让我们的感知里,只有哇程序跑满了CPU,还不错它在正常工作了。但是一般的mtalab线程他也是单线程工作的,所以我们需要写关于多线程的代码,这样的,他才能在多个核心和线程上跑满CPU。

参数设置

在这个地方我们可以设置集群的相关信息,其实也只是需要设置并行池进程的数量,以及工作的线程数。在右下角点击编辑之后可以编辑。

在这里插入图片描述

据我测试numworks好像不会超过CPU核心数量。我这个电脑是个8核16线程的电脑,所以我将上面设置为8,将下面设置为2,进行代码测试。

for?parfor!

如题,我们在进行循环计算的时候可以使用parfor来进行计算。parfor会将循环分配到多个并行计算池里面进行计算,这样就大大加快了计算速度。值得注意的是使用 parfor 时,循环的每次迭代必须独立,不能有数据依赖关系,也就是进程锁问题,数据不能相互干扰。巧的是,在我的计算任务里面,各个种群之间恰好是相互独立的。还有一点值得注意的是,如果是有多层嵌套循环,parfor尽可能放在最外层,而且只需要写一遍就行。

测试

这是一段矩阵求特征值的代码,分别比较将循环里面的for和parfor进行测试。

<code>% 开始计时

tic;

% 矩阵尺寸和数量

matrixSize = 1000; % 矩阵的大小

numMatrices = 100; % 矩阵的数量

% 预分配空间

eigenvalues = zeros(matrixSize, numMatrices);

% 开始并行计算

parfor i = 1:numMatrices

% 生成随机矩阵

A = rand(matrixSize);

% 计算特征值

eigenvalues(:, i) = eig(A);

end

% 结束计时并输出时间

elapsedTime = toc;

fprintf('计算所使用时间: %.2f 秒\n', elapsedTime);

在使用parfor情况下,我们的计算时间为20.22秒,cpu直接拉满了,如图所示

在这里插入图片描述

注意,第一次启动线程池会花费一定的时间,所以第一次时间很长

在这里插入图片描述

在不使用parfor的情况下,我们的计算时间为47秒左右,CPU占用率只有50%左右,如图。

在这里插入图片描述

在这里插入图片描述

其实看两幅图就知道CPU的状态有着天壤之别,按理来说,开了8个核心,但是实际上好像速度并没有跑快很多,只多了两倍,个人认为有如下几点原因

我的电脑还开了很多其他的软件,其他核心的资源也是在被占用的,系统肯定优先调用较为空闲的核心来满足你的计算任务在多个并行池之间,数据交换是需要耗费一定的时间的,所以效率达不到所谓的8倍

结尾

最终在CPU服务器上,我也是跑满了计算资源。各个线程的线条,一直在上下波动,我可能猜测是在分配计算资源吧,也就是数据交换。

在这里插入图片描述

关于matlab的CPU占用率低,以及并行池,有很多深入的资料,以及很多方法进行操作,这里只是抛砖引玉,提出并行计算的概念,这个工具包也是matlab2012之后就开始支持了。

个人感悟,我画了大概几个小时,进行相关检索了解相关知识,而针对我的计算而言,我让我的计算时间从2天优化变成了2-3个小时。所以有些时候不能将就,需要深究一些问题,这样才能效率能得到提高,并且自己得到进步!



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。