How to use libpointer inside parfor loop?

3 次查看(过去 30 天)
Hello,
i have a problem with libpointer and parfor loops. I want to access several USB cable(same time) with callib(read/write) but i need libpointer for them.
If i try to open the channel and init the channel before parfor loop, i cant use the libpointer inside because they disappear.
Is there any way to access libpointer inside parfor loop without to open/init/close the whole usb channel each time ?
% here some description
%open the channel and save the pointer under pChannelHandleArr
calllib(Libname,'SPI_OpenChannel',i-1,pChannelHandleArr{i,1});
% init the channel with given pChannelHandle
calllib(Libname,'SPI_InitChannel',pChannelHandleArr{i,1},ChConfig);
%transfer data to USB or read USB(SPI_Read) with given pChannelHandle
calllib(Libname,'SPI_Write',pChannelHandleArr{i,1},DataToWrite,size(DataToWrite,2),pNumBytesTransferredArr{i,1},transfer_options);
%clse channel with given handleArr
status=calllib(Libname,'SPI_CloseChannel',pChannelHandleArr{i,1});
if my communication is every 500ms then i need to do this all again.
here is a small example of libpointer and my problem
fprintf(' before loop');
%create var as libpointer
pNumchannels = libpointer('uint32Ptr',255);
fprintf(' LOOP BEGINN');
parfor i=1:3
%the var pNumchannels is empty here, the pointer is not there anymore
pNumchannels
end
fprintf(' endBEGINN');
is there any way to open the channel, save the pointer var and use it inside parfor loops?
best Regards,
Roman

回答(1 个)

Edric Ellis
Edric Ellis 2022-1-11
I think you should be able to do this using parallel.pool.Constant. I think you might need 2 of them in fact - one to manage the channel, and one for the libpointer. Something a little bit like this:
chanConst = parallel.pool.Constant(@setupChannel, @teardownChannel);
ptrConst = parallel.pool.Constant(@() libpointer('uint32Ptr',255));
parfor i = 1:N
% use ptrConst.Value
end
% Function to setup the channel. This must return a value. You will need to
% deal with the arguments to `calllib` somehow...
function v = setupChannel()
% Stuff like this
calllib(Libname,'SPI_OpenChannel',i-1,pChannelHandleArr{i,1});
% I don't think you need an actual value?
v = [];
end
% Function to tear down the channel. This gets the value returned by
% setupChannel
function teardownChannel(v)
calllib(Libname,'SPI_CloseChannel',pChannelHandleArr{i,1});
end
  3 个评论
Roman
Roman 2022-1-14
Maybe my question is not clear.
Im trying to create some libpointer infront of a parfor loop and use them inside parfor loop.
i think this parallel.pool.constant is a good thing but i cant manage to get it work
clear all
clc
Libname = 'libMPSSE';
if ~libisloaded(Libname)
loadlibrary(Libname, 'libMPSSE_spi_matlabFriendly.h');
% disp(['loaded' num2str(i)]);
end
ptrConstU32 = parallel.pool.Constant(@() libpointer('uint32Ptr',255));
ptrConstVoid = parallel.pool.Constant(@() libpointer('voidPtr',255));
pChannelHandle = libpointer('uint32Ptr',255);
status = calllib(Libname,'SPI_OpenChannel',1,ptrConstU32.Value);
fprintf('SPI_OpenChannel channel: %d --> %s \n',1,getFTStatus(status) );
ptrConstVoid2 = parallel.pool.Constant(ptrConstU32);
disp(ptrConstU32.Value.value)
disp(ptrConstVoid2.Value.Value.value)
disp('parforBeginn');
% Run multiple PARFOR loops accessing the data.
parfor k = 1:1
Libname = 'libMPSSE';
if ~libisloaded(Libname)
loadlibrary(Libname, 'libMPSSE_spi_matlabFriendly.h');
% disp(['loaded' num2str(i)]);
end
disp(ptrConstU32.Value.value)
disp(ptrConstVoid2.Value.Value.value)
pChannelHandle(k) = libpointer('uint32Ptr',255);
pChannelHandle(k) = ptrConstU32.Value
%disp(ptrConstU32.Value.value)
%disp(pChannelHandle.value)
status = calllib(Libname,'SPI_CloseChannel',ptrConstU32.Value);
fprintf('SPI_CloseChannel channel: %d --> %s \n',1,getFTStatus(status) );
end
disp('parforend');
status = calllib(Libname,'SPI_CloseChannel',ptrConstU32.Value);
fprintf('SPI_CloseChannel channel: %d --> %s \n',1,getFTStatus(status) );
its just always not available inside the parfor loop
output:
__________________________________________________________________________
SPI_OpenChannel channel: 1 --> FT_OK
2810160208 %before loop it is available
2810160208 %this also
parforBeginn
255% inside the loop the value dissapear
255% inside the loop the value dissapear
SPI_CloseChannel channel: 1 --> FT_OTHER_ERROR % cant close the channel because the pointer is wrong.
parforend
%after the parfor loop its working again
SPI_CloseChannel channel: 1 --> FT_OK
______________________________________________________________________
as you see i already tried to put that constant inside another constant, but its also not working.
Edric Ellis
Edric Ellis 2022-1-14
编辑:Edric Ellis 2022-1-14
Remember that each worker is a separate process, and so the libpointer instances you create in each process are completely unconnected from each other. parallel.pool.Constant here is simply a way to let you create a libpointer on each worker.
I think it would help if you can separate out the setup and cleanup phases that each worker process needs to perform from the independent pieces in the body of the parfor. Here's a concrete example, adapted from the doc example for libpointer. I hope this makes some sense. (I've made use of parfevalOnAll here for setup and cleanup since there is no "object" I need to track that represents the library)
%% Create a pool if required and available
if isempty(gcp('nocreate')) && canUseParallelPool
parpool('local',3);
end
%% Load the library on each worker
% Note using fetchOutputs here only to check for errors. The function
% 'doLoadLibrary' performs all necessary setup steps that must be performed
% on each worker
fetchOutputs(parfevalOnAll(@doLoadLibrary, 0));
%% Create a libpointer on each worker
% Each worker will allocate a doublePtr with value 1.0.
xConst = parallel.pool.Constant(@() libpointer('doublePtr', 1.0));
%% Use a parfor loop to modify the value in xConst
% In this case, the value inside xConst isn't actually "Constant" - it has
% "handle" semantics, so we can modify the underlying value.
parfor ii = 1:10
% Each worker has a separate xConst.Value
myPtr = xConst.Value;
% Set the value stored in the pointer to be the loop index
myPtr.Value = ii;
% Call into the shared library to perform the operation
calllib('shrlibsample','multDoubleRef', myPtr);
% Return this worker's current value
out(ii) = myPtr.Value;
end
disp(out)
5 10 15 20 25 30 35 40 45 50
%% Cleanup - unload the library on each worker
fetchOutputs(parfevalOnAll(@unloadlibrary, 0, 'shrlibsample'))
%% Function to load the library on the workers
function doLoadLibrary()
if ~libisloaded('shrlibsample')
addpath(fullfile(matlabroot,'extern','examples','shrlib'))
loadlibrary('shrlibsample')
end
end

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Data Type Identification 的更多信息

产品


版本

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by