WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Schleifen-Index Problem

 

BlackWolf
Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.06.2015, 10:52     Titel: Schleifen-Index Problem
  Antworten mit Zitat      
Hallo Zusammen,

ich versuche derzeit einen Datensatz in kleinere zu zerlegen und diese laufend aufzusummieren.

Hier mein bisheriger, nicht funktionierender Code:
Code:

A_sum = 0;
for i=20000:180000
    if Data(i) >= 150
        for j=1:40000
%             j=i-20000;
            A_temp(j,:) = Data(j(i-20000));
            A_sum(j) = A_sum(j) + A_temp(j);
        end
        i=i+25000;
    end
end
 

Nun eine kleine Erklärung wie ich mir das vorstelle:
Ich habe einen Datensatz Data. Dieser ist 200000 Samples groß.
Die ersten 20000 brauche ich nicht, also lasse ich meinen Index ab 20000 laufen und auch nicht über den gesamten Datensatz.

Jetzt zum Hauptteil.
Immer ab einem Grenzwert von 150 (Amplitude) soll ein Teil des Datensatzes in einem Temporären Vektor gespeichert werden>A_temp und dieser dann in einem anderen Vektor aufsummiert werden>A_sum.

Zum eigentlichen Problem:
Sobald die FOR-Schleife für j beginnt will ich das in A_temp 40000 Werte gespeichert werden. Und diese sollen genau -20000 bis +20000 um den Schwellwert an der Stelle i sein. Leider weiß ich nicht genau wie ich das machen soll.

Sobald das abgeschlossen ist soll der Vektor A_temp zu A_sum aufaddiert werden. Der Index i wird danach um +25000 Werte verschoben, damit der nächste Schwellwert nicht doppelt vorkommt.

Ich hoffe jemand hat vielleicht eine Idee.

Schonmal vielen Dank für eure Hilfe
Mark

Zuletzt bearbeitet von BlackWolf am 29.06.2015, 12:08, insgesamt einmal bearbeitet
Private Nachricht senden Benutzer-Profile anzeigen


BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.06.2015, 11:49     Titel:
  Antworten mit Zitat      
So, ich hab den ganzen Algorithmus schonmal etwas verbessert:

Code:

A_sum = 0;
for i=1:N
    if Data(i) >= 150
        i=i-20000;  % i = 18518
        for j=i:i+40000
            A_temp(j,:) = Data(j);
            A_temp = A_temp(A_temp~=0);
        end
        % i = 18518
        A_sum = A_sum + A_temp;
        i=i+40000;
        % i = 58518
    end
end
 


Das Problem ist leider, das nach dem ersten Durchlauf des j-Index zwar der Index i auf +40000 gesetzt wird, aber sobald die erste for-Schleife wieder weiter geht, zählt diese nicht von i=58518, sondern wieder von 18518... Question
Und die j-for-Schleife macht danach natürlich auch nur mist..

Die Frage ist also, wie schaffe ich es das der Index i von 58518 weiter zählt und nicht wieder von vorne beginnt??
Private Nachricht senden Benutzer-Profile anzeigen
 
BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.06.2015, 12:30     Titel:
  Antworten mit Zitat      
Okay,
der Index i zählt am Anfang bis 38518, dort tritt zum ersten mal der Wert 150 auf. Dann folgt die j-Schleife. Die macht auch alles einwandfrei.
Allerdings wenn ich den Index i nachdem "end" der j-Schleife auf +40000 setze bringt das anscheinend gar nichts, weil der i-Index nachdem "end" der if-Anweisung bei 38519 weiter zählt.

Jetzt ist die Frage wie ich den Index i um plus 40000 verschoben weiter zählen lasse?
Private Nachricht senden Benutzer-Profile anzeigen
 
BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.06.2015, 12:55     Titel:
  Antworten mit Zitat      
Und ich hab meine Frage selber beantwortet Wink

Hier der funktionierende Code:
Code:

A_sum = 0;
for i=1:1000:N
    if Data(i) >= 150
        A_temp = 0;
        for j=i-20000:i+20000
            A_temp(j,:) = Data(j);
            A_temp = A_temp(A_temp~=0);
        end
        A_sum = A_sum + A_temp;
    end
end
 

Den Schleifenindex darf man natürlich nicht innerhalb der Schleife ändern wie ich es vorher getan habe. Wieder was dazu gelernt Smile
Private Nachricht senden Benutzer-Profile anzeigen
 
BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.06.2015, 13:27     Titel:
  Antworten mit Zitat      
Okay, es gibt vielleicht doch noch was wo mir evtl. wer helfen könnte.

Kann man das ganze schneller bzw effizienter gestalten?
Mit einem großen Datensatz dauert das so sehr lange...
Private Nachricht senden Benutzer-Profile anzeigen
 
Winkow
Moderator

Moderator



Beiträge: 3.842
Anmeldedatum: 04.11.11
Wohnort: Dresden
Version: R2014a 2015a
     Beitrag Verfasst am: 01.07.2015, 01:35     Titel:
  Antworten mit Zitat      
mir ist da einiges noch nicht ganz klar und ohne konkreten datensatz kann man schwer rumexperimentierne. es ist immer einfacher wenn ein lauffähiges beispiel gepostet wird.
ich finde den code sowieso seltsam.
dein i läuft ja von 1 bis irgendwo und dein j aber von i-20000... negative indizes sind aber garnicht zugelassen. das sollte abhängig von den daten einen fehler geben.
anstadt der äußeren schleife kann man bestimmt auch find und logisches indizieren benutzen.
deine matrix A_temp dürfte auch sehr viele nullen haben da du einfach irgendwo indizierst. und danach alle nullen löscht.... das macht für mich keinen sinn.
ich verstehe auch nicht die summe danach... da werden doch arrays unterschiedlicher größe addiert?...
das ist mir alles unklar.
_________________

richtig Fragen
Private Nachricht senden Benutzer-Profile anzeigen
 
BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.07.2015, 09:27     Titel:
  Antworten mit Zitat      
Hey Winkow.
Erstmal vielen Dank für deine Antwort.
Ich poste jetzt mal den vollständigen und aktuellen Code:
Code:

Data = importdata('Signal_200000.txt');    % Reading data

N = length(Data);

A_sum = 0;
i=1;

while i < N
    i=i+1;
    if Data(i) >= 140 && i < 20100
        i=i+1000;
    end
    if Data(i) >= 140 && i+20100 > N
        break
    end
    if Data(i) >= 140
        A_temp = 0;
        for j=i-20000:i+20000
            A_temp(j,:) = Data(j);
            A_temp = A_temp(A_temp~=0);
        end
        A_sum = A_sum + A_temp;
        i = i+2000;
    end
end
 


Ich habe aussen eine while-Schleife, die über die komplette länge meines Datensatzes läuft. Dann folgen die beiden ersten if-Anweisungen, die dafür da sind, dass der Datensatz vorne und hinten angepasst wird, damit die for-Schleife nicht ins Leere läuft.
Zur dritten if-Anweisung. Wenn mein Datensatz nun einen Schwellwert von >= 140 erreicht, wird das Temporäre Array A_temp Null gesetzt.
Danach kommt die for-Schleife, die 40000 Werte in A_temp packt.
Diese 40000 Werte sind in einem Intervall von -20000 < i < 20000 und i hat einen Wert von mindestens 20100 (siehe erste if-Anweisung), so vermeide ich negative Indizes.
Und zum guten Schluss wird das ganze aufsummiert, so das bei jedem neuen Schwellwert A_temp neu gefüllt wird und dann auf A_sum draufsummiert wird.
Danach wird der Index i noch um +2000 verschoben damit vermieden wird das der selbe Ausschlag nochmal drauf gerechnet wird.

Die Signal-Datei geb ich jetzt auch mal dazu.

Das Programm macht genau den Job den ich will. Nur ab einer grösseren Anzahl von Werten, wo ich z.B. 50 mal einen Schwellwert erreiche mit 5.000.000 Datenpunkten dauert das viel zu lange. Ein bis zwei Stunden und das ist nicht gut...
Daher bin ich für jegliche Optimierung offen.

PS: Das Nullen Problem in A_temp löse ich derzeit mit dem Ausdruck
Code:
A_temp = A_temp(A_temp~=0);


Signal_200000.txt
 Beschreibung:

Download
 Dateiname:  Signal_200000.txt
 Dateigröße:  976.56 KB
 Heruntergeladen:  375 mal
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 01.07.2015, 09:39     Titel:
  Antworten mit Zitat      
Hallo,

hast du mal den Profiler laufen lassen? Wo wird denn die meiste Zeit verbraucht?

Ich würde hier nicht importdata verwenden, da das ja die (dir vermutlich bekannte) Dateistruktur erstmal analysieren muss. textscan kann da deutlich effizienter sein.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 01.07.2015, 10:05     Titel:
  Antworten mit Zitat      
Hallo BlackWolf,

Das sieht merkwürdig aus:
Code:
A_temp = 0;
for j=i-20000:i+20000
   A_temp(j,:) = Data(j);
   A_temp = A_temp(A_temp~=0);
end
A_sum = A_sum + A_temp;

A_temp ist im Allgemeinen nach der Schleife ein Vektor. Diesen dann zu A_sum zu addieren funktioniert nur, wenn alle A_temp die gleiche Größe haben. Ist das immer der Fall? Oder meinst Du:
Code:
A_sum = A_sum + sum(A_temp)


Es ist extrem Zeitraubend, den Vektor A_temp in jeder Iteration zu vergrößern und wieder zu verkleinern. Dabei muss immer eine neues Array im Speicher alloziert werden, was eine teure Operation ist, alle bisherigen Speicherzellen kopiert werden und der alte speicher freigegeben werden. Und das 80'000 mal.
Das geht effizienter:
Code:
A_temp = Data(i-20000:i+20000);
A_temp = A_temp(A_temp~=0);
A_sum = A_sum + A_temp;   % bzw. A_sum + sum(A_temp);

Das erspart 79'999 mal das Allozieren und Kopieren eines Vektors. Das sollte also bedeutend schneller sein.

Wozu dient eigentlich das A_temp(j,:) = Data(j) ? Muss hier wirklich in das j.te Element von A_temp geschrieben werden? Warum?

Ist in dieser Schleife wirklich sichergestellt, dass i>20000 ist? Nein!
Code:
while i < N
    i = i+1;
    if Data(i) >= 140 && i < 20100
        i=i+1000;   % Jetzt kann i=1001 sein und Data(1001)=140
    end
    if Data(i) >= 140
        A_temp = 0;
        for j=i-20000:i+20000  % Hier ist i dann 1001-20000 !!!
 


Du hast mehrere verschiedene Codes gepostet, die unterschiedliche Dinge berechnen. Mal geht die Schleife in 1000er Schritten, mal nicht. Insofern weiß ich nicht genau, was das Programm eigentlich leisten soll. Die Version von 29.06.2015, 10:52 sieht noch am stabilsten aus:
Code:
A_sum = 0;
for i=20000:180000
    if Data(i) >= 150
        for j=1:40000
            A_temp(j,:) = Data(j(i-20000));
            A_sum(j) = A_sum(j) + A_temp(j);
        end
        i=i+25000;
    end
end

Und die bereinigt:
Code:
A_sum = 0;
i = 20000;
while i <= 180000
    if Data(i) >= 150
        A_sum = A_sum + sum(Data(i-20000:i+20000));
        i = i+25000;
    else
        i = i + 1;
    end
end

Statt die Schleife über alle Elemente von Data laufen zu lassen, kannst Du auch zunächst die interessanten Punkte finden:
Code:
Index = find(Data > 150);

Dabei können die Punkte allerdings auch einen Abstand < 20'000 haben, was man berücksichtigen müsste.

Gruß, Jan

Zuletzt bearbeitet von Jan S am 01.07.2015, 10:09, insgesamt 2-mal bearbeitet
Private Nachricht senden Benutzer-Profile anzeigen
 
BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.07.2015, 10:06     Titel:
  Antworten mit Zitat      
Hallo Harald,
ich denke Jan S hat gerade gezeigt wo die meiste Zeit verbraucht wird, das geht so jetzt schon wesentlich schneller. Den Profiler hab ich noch nie vorher benutzt, werde es aber mal ausprobieren.

Hallo Jan,
vielen Dank für diese Verbesserung. Es geht wie schon erwähnt nun wirklich schneller.

A_temp(j,: ) = Data(j) war komplett sinnfrei wenn ich mir das jetzt so ansehe.

Zitat:
Ist in dieser Schleife wirklich sichergestellt, dass i>20000 ist? Nein!

Gerade denke ich schon das das sichergestellt wird, da ein Peak maximal eine Breite von 950 besitzt und wenn der Wert von >= 140 das erste mal erreicht wird bevor i > 20000 wird, wird es dadurch einige 10000 samples dauern bis Data(i) >= 140 ist.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 01.07.2015, 10:09     Titel:
  Antworten mit Zitat      
Hallo BlackWolf,

Ich hatte meinen Post gerade nochmal überarbeitet. Am Ende steht eine kompakte und einfache Schleifen-Version, die ich bevorzugen würde.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
BlackWolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 17
Anmeldedatum: 09.03.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.07.2015, 10:18     Titel:
  Antworten mit Zitat      
Hallo Jan,

das habe ich mir jetzt auch mal angeschaut und das Programm läuft jetzt sehr schnell und so wie ich es mir vorstelle.

Zu der bereinigten Version von dir, durch
Code:
A_sum = A_sum + sum(Data(i-20000:i+20000));

habe ich am Ende eine Summe und keinen Vektor mit 40000 Werten.
Aber da überlege ich mir nochwas.
Fakt ist das mein Code nun wesentlich schneller läuft als am Anfang und dafür bin ich wirklich dankbar!

Grüsse,
BlackWolf
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.