我有一个相对较大的文件,我想使用GUIDE绘制一个交互式绘图,绘制文件的一部分,并在scrollEvent上更新窗口。 (数据适当重新绘制)。
为此,获取大小为窗口大小4倍的缓冲区,当窗口的中心达到缓冲区的75%时,将重新获取缓冲区,以便窗口位于新缓冲区的中心。
问题在于,当使用fread
时,它当然会阻塞直到完成。(这在视觉上令人不安)
我尝试创建一个单独的readData
函数,该函数使用f = parfeval(gcp(),@readData,1,datafile)
进行调用,而[~,buffer]=fetchNext(f)
buffer
将保留handles.datafile
。
问题:即使在我的示例中(见下文)readData
只调用一次,但每次后续绘图都非常慢(不使用parfeval
时的运行时间的10倍)。
示例:
./test.dat
由dd if=/dev/urandom of=test.dat bs=100000 count=1024
**这是获取异步代码的同步代码,注释掉parfeval
和fetchNext
函数定义,影响并行代码。
function test()
f = figure('Toolbar','none','Menubar','none');
ax = axes(f);
data = struct( 'file','./test.dat',...
'buffer',[],...
'window',[0,100000]);
p = gcp();
data.fileReader = parfeval(p,@readData,1,data);
handles = struct('axes',ax,'figure',f,'data',data);
guidata(f,handles);
set(f,'WindowScrollWheelFcn',@scrollHandler);
end
function f = parfeval(~,fun,~,in1)
f = struct('output',fun(in1));
end
function [id,out] = fetchNext(f,varargin)
id = 1;
out = f.output;
end
function buffer = readData(data)
file = fopen(data.file,'r');
buffer = fread(file,[128,400000],'int16');
fclose(file);
end
function scrollHandler(hObject, eventdata, ~)
handles = guidata(hObject);
ax = handles.axes;
C = get (ax, 'CurrentPoint');
XLim = get(ax, 'XLim');
YLim = get(ax, 'YLim');
if XLim(1)<=C(1,1) && XLim(2)>=C(1,1) && ...
YLim(1)<=C(1,2) && YLim(2)>=C(1,2)
tic;
window = handles.data.window;
if isstruct(handles.data.fileReader) || handles.data.fileReader ~= -1
fprintf('Reading from file\n');
[~,handles.data.buffer] = fetchNext(handles.data.fileReader);
handles.data.fileReader = -1;
end
if eventdata.VerticalScrollCount > 0 && window(2) < 399000
window = window + 1000;
else
if window(1) > 1000
window = window - 1000;
end
end
handles.data.window = window;
guidata(hObject, handles);
plot(ax,handles.data.buffer(65,window(1)+1:window(2)));
toc
end
end
答案 0 :(得分:1)
这确实非常神秘。问题似乎是guidata
与parallel.FevalFuture
返回的parfeval
之间的某种互动。作为一种解决方法,您可以简单地避免覆盖结构的该元素。换句话说,删除行
handles.data.fileReader = -1;
您还需要检查handles.data.fileReader.Read
,确保在已完成的未来再次尝试再次致电fetchNext
。