2017-06-20 2 views
0

Ich habe eine relativ große Datei und ich möchte ein interaktives Plot mit GUIDE erstellen, das ein Segment der Datei plottet und bei scrollEvent wird das Fenster aktualisiert. (Die Daten werden entsprechend neu erstellt).Leistungsverlust mit Matlab parfeval?

Zu diesem Zweck wird ein 4-mal größerer Puffer als das Fenster abgerufen, und wenn der Mittelpunkt des Fensters 75% des Puffers erreicht, wird der Puffer erneut abgefragt, so dass sich das Fenster im Mittelpunkt des neuen Puffers befindet.

Das Problem dabei ist, dass, wenn fread es natürlich Blöcke mit bis getan. (Die optisch störend ist)

Was ich ist versucht, eine separate readData Funktion zu schaffen, die mit f = parfeval(gcp(),@readData,1,datafile) und auf [~,buffer]=fetchNext(f) die buffer aufgerufen wird wird auf handles.datafile beibehalten.

Problem: Auch wenn in meinem Beispiel (siehe unten) readData wird nur einmal aufgerufen, jede nachfolgende Plotten unglaublich langsam ist (10x die Laufzeit, wenn nicht parfeval verwenden).

Beispiel:

./test.dat von dd if=/dev/urandom of=test.dat bs=100000 count=1024

generiert wurde ** Dies ist der Synchroncode des asynchronen eins zu bekommen, kommentieren Sie die parfeval und fetchNext Funktionsdefinitionen, die parallel diejenigen Shadowing.

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

Ich habe versucht, dies mit Ihrem Code zu reproduzieren, aber es war mir nicht klar, wie Sie damit richtig umgehen. Es wäre sehr hilfreich, wenn Sie eine einfachere Standalone-Code-only-Reproduktion erstellen könnten. Es scheint auch so, als ob du irgendwie andeuten würdest, dass ein einziger vorheriger Aufruf von 'parfeval' irgendwie das anschließende Plotten verlangsamt? – Edric

+0

@Edric hat das Beispiel auf einen Nur-Code aktualisiert. – Adam

Antwort

1

Dies ist in der Tat sehr mysteriös. Das Problem scheint eine Art von Interaktion mit guidata und der parallel.FevalFuture, die von parfeval zurückgegeben wird. Als Workaround können Sie einfach das Überschreiben dieses Elements der Struktur vermeiden. Mit anderen Worten, entfernen Sie die Zeile

handles.data.fileReader = -1; 

Sie werden auch handles.data.fileReader.Read überprüfen, müssen Sie nicht fetchNext wieder auf einer bereits abgeschlossene Zukunft anrufen stellen Sie sicher versuchen.

+0

das funktioniert tatsächlich, danke – Adam