Can Win32::OLE be used in parallel to start multip

2019-07-25 11:12发布

问题:

When Parallel::Loops is combined with Win32::OLE to create multiple instance of Matlab, if we use

my $ML = Win32::OLE->new('Matlab.Application') or die "Cannot start MATLAB"

in each loop, the program crashes showing an unhandled exception.

If drop the my before $ML then it works, but at any time only one instance is running.

回答1:

I'm not sure what is the benefit of creating multiple MATLAB COM servers in a parallel loop.

By default the server is created in shared mode, ie shared by all instances. The MATLAB engine is exposed to the user as single-threaded, so in your case all the clients computations are run in serial, not in parallel.

Fortunately you create MATLAB COM server in dedicated mode:

Win32::OLE->new('Matlab.Application.single')

See this page for more info

PS: I know very little Perl :)



回答2:

You really should show your full code.

If you are setting my $ML inside the anonymous subroutine passed to Parallel::Loops then you are setting the value in only a child process and the value will no be available to the parent.

It is unclear what you are using the Matlab processes for, but they will not persist after the death of their parent, which is one of the child processes that your main program starts.

You could try declaring my @matlabs outside the loop, and then doing

push @matlabs, Win32::OLE->new('Matlab.Application')

within the loop. But if you a number of persistent Matlab processes then why not just run a simple for loop?



回答3:

Parellel::Loop are tested not working with Win32::OLE to start multiple instance of Matlab, but Parellel::Forkmanager works by using the "single" trick from Amro and clue from http://www.perlmonks.org/bare/?node_id=894058 for an error of "CoInitialize has not been called":

before the loop use:

use Win32::OLE; # qw(EVENTS); #Win32::OLE(0.1709) error 0x800401f0: "CoInitialize has not been called"  
Win32::OLE->Initialize();  

and inside the loop use:

my $ML = Win32::OLE->new('Matlab.Application.single') or die "Cannot start MATLAB";  
$ML->{'Visible'}=0;  
$ML->Execute('try;cd \''.$wkdir.'\';'.$executable.' '.$file.' '.$countfile.';catch;end;quit;');  

The purpose of use OLE instesd of just using:

system('matlab -automation -wait -r "try;cd \''.$wkdir.'\';'.$executable.' '.$file.' '.$countfile.';catch;end;quit;');  

is to hide the Matlab window, we just want it to do the work but we get the honor. Using Perl to achieve the parallellized matlab parfor effects we can keep all the available CPU busy doing tasks allocated before the parellel loop and collect/combine the results after that loop.



回答4:

With further experiment, it is found that the error of Parallel::Loop and the error of Win32::OLE(0.1709) error 0x800706be: "The remote procedure call failed or Free to wrong pool when using Parellel::ForkManager can be both avoided by a suggestion from http://www-01.ibm.com/support/docview.wss?uid=swg21261292 and http://search.cpan.org/~gsar/libwin32-0.191/OLE/lib/Win32/OLE/TPJ.pod about silence the warning. All the code need to be included inside the parallel loop, and this are the working version:

    require Win32::OLE;
    import Win32::OLE;
    Win32::OLE->Initialize();
    no warnings qw(once); 
    $Win32::OLE::Warn = 0;
    my $ML = Win32::OLE->new('Matlab.Application.single') or die "Cannot start MATLAB";
    $ML->{'Visible'}=0;
    $ML->Execute('try;cd \''.$wkdir.'\';'.$executable.' '.$file.' '.$countfile.';catch;end;quit;');