Matlab 是不支持多线程的,貌似这是一个truth ,但是有些时候是非常需要Matlab能够多任务处理的。你比如一个需要一个线程去录音,一个线程进行信号处理实时反馈。
我能想到的一些用matlab用作多线程的方法有这些:
1、定时器
2、使用外部可执行文件
3、使用Csharp或者C++的混合编程库
4、使用java的多线程机制,自己开发自定义类
5、使用matlab的内存映射机制
1、定时器
首先能想到的是 matlab的定时器:
下面是一个定时器的定义:
t_activer_timer = timer('TimerFcn', {@TimerFcn1,u}, 'Period', 6.1, 'ExecutionMode', 'fixedRate');
function TimerFcn1(obj,event,u)
%你自己的操作
end
这上面的图是不是你脑中的 定时器工作的流程图,基本上来说,是没有多大问题的,但实际上 timer只适合 触发 处理量比较小的 的轻型函数/模块
比如:显示个字符啊,写出写入文件啊,在MatlabGUI,触发打印一些屏幕信息啊,但实际上对于timer的 proc处理函数如果工作量比较大的话,就看出问题来了
下面才是真正的流程图
你可以在timer的timerfunction中加比较长的pause试试,看看是不是主线程还在继续??所以这种方式只能认为是:
timer的timerfunction和主程序并不是真正含义上多线程,timerfunction只适合做一些‘轻量级“的处理,比如算个时间啊,反馈个值啊,给界面更新一下啊
2、使用外部可执行文件
有的同学肯定说,执行system外部的一些exe文件,也是需要等待的,但是笔者经过查找,这里面有加 &的区别
比如下面的两个,第二个system加&的 就可以快速的执行下一个语句
system('program arg1 arg2'); % blocking, synchronous system('program arg1 arg2 &'); % non-blocking, asynchronous
matlab 给出的解释是
The following trailing character has special meaning:
'&' - For console programs this causes the console to
open. Omitting this character causes console
programs to run iconically. For GUI programs,
appending this character causes the application to
run in the background. MATLAB continues processing.
3、使用Csharp或者C++的混合编程库
实现方法主要是使用matlab的函数: NET.addAssembly
需要实现你在DotNet或者c++里面enable多线程,把他们build成dll库,在matlab使用NET.addAssembly来load这个库,比如
NET.addAssembly('C:\Yair\Code\NetThread.dll');
start(My.NetThread('F:\test.data',data));至于怎么实现Csharp或者C++之间的混合编程,网络上有不少现成的例子,这不是本文章讨论的重点
start(My.NetThread('F:\test.data',data));4、使用java的多线程机制,自己开发自定义类
Matlab就是基于java平台的,貌似我使用java的类,经常用到的是在GUI上面,比如我要使用一个比较特殊的button,java中才有一些能定义属性的控件,这里面我们要用的是一个叫Thread的类,java中的thread的类是支持多线程的。
初步的想法就是继承java中的thread类,自己定义个类(当然了,你这个类方法要处理你自己的数据)
在这之前要实现查一下你matlab中的java版本
version -java
ans = Java 1.7.0_60-b19 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
要去sun或者哪里下载一个和这个一样版本的java sdk给装上,否则你javac出来的class文件,matlab不认。
比如我随便写一个java的类,它是不断的往外抛数据
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class MyJavaThread extends Thread
{
String filename;
double[] doubleData;
public MyJavaThread(String filename, double[] data)
{
this.filename = filename;
this.doubleData = data;
}
@Override
public void run()
{
try
{
for (int i=0; i < doubleData.length; i++)
{
System.out.println(filename);
System.out.println(i);
}
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
}
我是用javac编译一下(如果你有什么eclipse,javaeditor,jcreator,whatever只要能编译就行的IDE都可以)
javac.exe MyJavaThread.java
这时候生成出来的class文件就在matlab工程目录中
Matlab中你可以写像我这样的一段代码:
data = rand(1000,1);
javaaddpath('D:\MatlabWork\Matlab_UDP\UsingJavathreads') % path to MyJavaThread.class
start(MyJavaThread('test1.data',data)); % start running in parallel
start(MyJavaThread('test2.data',data)); % start running in parallel
这时候你可以看到是双线程在不断的往外抛数据
5、使用matlab的内存映射机制
这是这篇blog的干货了,前面的方法如果都不灵,对于你来说可以尝试一下这种。
如果一个Matlab真没法实现多线程,那我们就起两个Matlab!
一个PC机器上跑两个matlab也不算什么吧?两个matlab同时执行两个不同的m程序,然后它俩直接通讯不就实现多线程了么?
关键文件就是这两个matlab程序之间要实现数据共享,幸好啊,matlab已经提供了这个机制。
memmapfile : memmapfile Construct memory-mapped file object. M = memmapfile(FILENAME) constructs a memmapfile object that maps file FILENAME to memory, using default property values. FILENAME can be a partial pathname relative to the MATLAB path. If the file is not found in or relative to the current working directory, memmapfile searches down the MATLAB search path.我理解shared memory是内存映射,是内存和disk之间的映射;它既然把一个文件当成内存,那我们就借这个东风呗
你都是内存了,当然两个程序可以同时访问到(当然也必须要考虑两个matlab程序之间对内存的读写访问权限了)
说白了,一个读的时候,另一个别写,一个写的时候,另一个别读。
那就好办了!
使用这个方法就两步,先建立一个文件,然后建立memmapfile机制
filename = fullfile(tempdir, 'talk_answer.dat');
data = zeros(1,261122);%这是你要用到的共享内存的大小,注意,必须大小实现敲定好fwrite(f, data, 'double');
fclose(f);
m = memmapfile(filename, 'Writable', true, 'Format', 'double'); %设置好共享内存
你在另外一个m文件里面也同样写上面的代码。同时跑两个matlab 代码。
有同学肯定会问, 你怎么保证不能同时改写,很简单,你把上面的data(1) 首单元作为读写标记位好了。
或者用两个单元,data(1),data(2)作为读、和写的分别标记位!
这样就能保证没有冲突了。我试了一下,这种方式还是非常快的,访问速度比想象的要快。