Matlab多核CPU并行和多线程

简介

这里需要明白的概念有:多核、多进程、多线程、并行计算、并发计算的区别。

什么是多核
在计算机设计早期,为了响应更多计算性能的需要,单处理器系统发展成为多处理器系统。更现代的、类似的系统设计趋势是将多个计算核放到单个芯片。无论多个计算核是在多个CPU芯片上还是在单个 CPU 芯片上,我们称之为多核或多处理器系统。

多进程
进程就是正在进行的一个程序或者任务,而负责执行任务的是CPU,执行任务的地方是内存。程序运行时的过程就是进程,同一个程序执行两次就是两个进程了。

并发与并行
并发和并行都是“同时”在工作,对于并发而言,是“伪并行”,即看起来是同时运行,其实是频繁更换CPU执行的程序代码,加之中间延迟很小,从我们的视角来看感觉就像是程序在同时运行;并行计算才是真正的同时计算,仅有多核才能是并行。

例子:你正在吃饭,电话响了
并发:放下筷子去接电话,接完电话然后继续吃饭
并行:一边接电话一边吃饭

并发: 当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

并行: 当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
注意这里讨论的并行性和并发性的区别。并行系统可以同时执行多个任务。相比之下,并发系统支持多个任务,允许所有任务都能取得进展。因此,没有并行,并发也是可能的。

在 SMP 和多核架构出现之前,大多数计算机系统只有单个处理器。CPU 调度器通过快速切换系统内的进程,以便允许每个进程取得进展,从而提供并行假象。这些进程并发运行,而非并行运行。

随着系统线程数量从几十个到几千上万个,CPU 设计人员通过增加硬件来改善线程性能的提高系统性能。现代 Intel CPU 的每个核经常支持两个线程,而 Oracle T4 CPU 的每个核支持 8 个线程。这种支持意味着,可以将多个线程加载到处理核以便快速切换。毫无疑问,多核计算机将继续增加多核数量和硬件线程支持。

强烈注意: 多核,多cup,多机是不同的概念。

多线程编程提供机制,以便更有效地使用这些多个计算核和改进的并发性。考虑一个应用,它有 4 个线程。对于单核系统,并发仅仅意味着线程随着时间推移交错执行(图 1),因为处理核只能同一时间执行单个线程。
在这里插入图片描述
不过,对于多核系统,并发表示线程能够并行运行,因为系统可以为每个核分配一个单独线程(图 2)。
在这里插入图片描述
多进程是并行计算,多线程是并发计算。

线程与进程
线程: 是程序执行流的最小单元,是系统独立调度和分配CPU(独立运行)的基本单位。
进程: 是资源分配的基本单位。一个进程包括多个线程。

区别

1.线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源。
2.每个进程都有自己一套独立的资源(数据),供其内的所有线程共享。
3.不论是大小,开销线程要更“轻量级”
4.一个进程内的线程通信比进程之间的通信更快速,有效。(因为共享变量)

多线程与多进程
多线程:同一时刻执行多个线程。用浏览器一边下载,一边听歌,一边看视频,一边看网页。。。
多进程:同时执行多个程序。如,同事运行YY,QQ,以及各种浏览器。

基于Matlab实现多线程运算

这里通常大家的电脑都是多核电脑了,自然希望同时执行多个程序的运算任务,这里就简介一下如何实现。
获取电脑核数、CPU数和GPU数量,知己知彼,如果是单核,也就没有多大必要设置这些了。也可以通过进程管理器查看,几个子窗口就是几核。

% 检查GPU数量
ngpus=gpuDeviceCount;
disp([num2str(ngpus) ' GPUs found'])

% 检查核心数量
ncores=feature('numCores');
disp([num2str(ncores) ' cores found'])

% 检查电脑CPU数量
import java.lang.*;
r=Runtime.getRuntime;
ncpus=r.availableProcessors;
disp([num2str(ncpus) ' cpus found'])

如果我们想要执行不同的程序或代码,方法有:
方法1:开多个Matlab(最直接) 由于Matlab软件体量大,不是特别适合,如果有四五个任务要执行,开四五个或更多的Matlab有点不是很现实。
方法2:把不同的程序写成 function ,分配给不同的task
方法3:把不同的程序写成 function ,利用parfor实现

利用 Matlab 进行并行计算时,还需要说明几个概念:
job : 即Matlab待完成的任务,job由一组 task(作业)组成。
task : 并行计算的基本单元,分配到Matlab worker执行
scheduler :负责管理Matlab 提交的job, 分配 task 到每一个 worker
worker: 是指工作单元,数目一般小于等于 CPU的核数。lab是特殊的一个worker,lab之间可以进行数据通信。

例子1,官方例子

t = createTask(j, F, N, {inputargs})
t = createTask(j, F, N, {C1,...,Cm})

首先创建一个工作,然后创建三个任务,三个任务都是调用rand函数生成随机数,三个任务的参数如后面的元包数组,要生成10x10 2x10 10x3的随机矩阵。

c = parcluster(); % Use default profile
j = createJob(c);
t = createTask(j, @rand, 1, {{10,10} {2,10} {10,3}});
submit(j);
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1});
disp(taskoutput{2});
disp(taskoutput{3});

上述方法,也可以写成

c = parcluster(); % Use default profile
j = createJob(c);
createTask(j, @rand, 1, {10,10});
createTask(j, @rand, 1, {2,10});
createTask(j, @rand, 1, {10,3});
submit(j);
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1});
disp(taskoutput{2});
disp(taskoutput{3});

还可以写成

c = parcluster(); % Use default profile
j = createJob(c);
pars = [10 10; 2 10; 10 3];
for i=1:3
	createTask(j, @rand, 1, {pars(i,1),pars(i,2)});
end
submit(j);
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1});
disp(taskoutput{2});
disp(taskoutput{3});

方法2,假设有两个以及以上不同函数需要同时执行,即两个或以上任务需要不同函数来实现。

function state = myplot(x,y)
    plot(x,y)
    state = 1;
    print(gcf,'-dpng','-r300','myplot.png'])
end


function state = mytxt(A)

    filename = 'mytxt.txt';%文件路径 + 文件名
    file_id = fopen(filename,'a+');
    for jj = 1:length(A)
        fprintf(file_id,'%.4f\r\n',A(jj));
    end
    fclose(file_id);
    state = 1;
end

par = 1:50;
x=-100:-1:100;
y = x.^2;

c = parcluster('local');
j = createJob(c); %开启一个job
createTask(j,@myplot,1,{x,y});
createTask(j,@mytxt,1,{par});
get(j,'Tasks')
submit(j);
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1});

例子3,上面的任务太小,假设两个任务都需要耗费许多时间。这个例子增加一些时间消耗,运行需要约20秒,设置了每次循环暂停1秒。

function state = mytxt(id)
    file = fopen(['mytext_ ' num2str(id) '.txt'],'a+');
    for i = 1:20
        fprintf(file,'%.4f\r\n',i);        
        pause(1)
    end
    fclose(file);
    state = 1; %函数状态
end

c = parcluster();
j = createJob(c);
createTask(j,@mytxt,1,{{1},{2},{3}});
get(j,'Tasks')
submit(j);
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1}); 获取进程的状态
disp(taskoutput{2});
disp(taskoutput{3});

性能简单比较,通过时间

tic
for i=1:3
    mytxt(i)
end
toc

tic
c = parcluster();
j = createJob(c);
createTask(j,@mytxt,1,{{1},{2},{3}});
get(j,'Tasks')
submit(j);
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1});
toc

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
方法3,此方法比较简单,使用方法如下,这个方法很简单且效率最高。

tic
parfor i=1:3
    mytxt(i)
end
toc
历时 20.123471 秒。

Parfor与createJob createTask的差异

差异1: createJob createTask启动和时间消耗都是比Parfor更高,如果对于长时间耗时的工作该差别不会太明显,但是对于测试阶段该区别显而易见。究其原因如下:使用createJob和createTask时,每个任务都在单独的MATLAB进程中运行,与parfor循环相比,这花费了更多的时间来启动。
差异2: parfor不可以嵌套循环,比如不可以:

parfor i=1:n
    parfor j=1:m
    	.....
    end
end

当然可以通过实现将参数设置好,通过单循环获取参数进行并行运算。经过实际测试还是推荐parfor,该过程可以输出中间过程,如果有错误会终止运行,而createtask无法输出中间过程。
差异3: parfor如果有一个并行运算崩溃有可能导致整个运算结束。而createJob createTask则不会,关掉matlab进程还在运行。这一点createJob createTask还是比较有用的。

Matlab无法开启并行Parallel运算解决方法

在Mac mini m1上,经过本人测试,如果2019未安装network license manager工具箱,就会导致无法进行并行运算,安装后即可。对于2020版本,不知道什么原因始终不可以开启。Windows以及其它IOS系统没有遇到过这种情况。

总结

多个进程执行完毕后,会自动释放其内存。由于理解等上述内容可能有错误,欢迎指出共同学习进步。

参考
https://www.cnblogs.com/purple5252/p/12957544.html
http://c.biancheng.net/view/1218.html
https://blog.csdn.net/weixin_44212633/article/details/111334042

  • 24
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值