Wer sieht hier Optimierungspotential -FOR-Schleife

Hallo,

ich habe einen Vektor (‚vektor‘), der Messdaten enthält: etwa 1,6 Mio. Einträge.
Die Messwerte verlaufen des öfteren vom positiven Bereich in den negativen und umgekehrt. Ich möchte nun die Vektoreinträge identifizieren, an denen eine solche Nullstelle vorliegt. Bisher benutze ich dafür den folgenden C++ Code:

for i = 1 :frowning:length(vektor)-1)
if (vektor(i) == 0)
nullstelle(z) = i;
z = z+1;
elseif ((vektor(i) 0))
nullstelle(z) = i;
z = z+1;
elseif ((vektor(i) > 0) & (vektor(i+1)

Hallo,

Ich möchte nun die Vektoreinträge
identifizieren, an denen eine solche Nullstelle vorliegt.
Bisher benutze ich dafür den folgenden C++ Code:

> for i = 1 :frowning:length(vektor)-1)  
> if (vektor(i) == 0)  
> nullstelle(z) = i;  
> z = z+1;  
> elseif ((vektor(i) 0))  
> nullstelle(z) = i;  
> z = z+1;  
> elseif ((vektor(i) \> 0) & (vektor(i+1)


Ich bin zwar nicht so der wahnsinnige C++-Guru, aber das sieht für mich überhaupt nicht nach C++ aus. Eher Pascal oder so.

Ich vermute, du kannst den Inhalt der Schleife auf das hier reduzieren (in pseudocode)



    
    if ((vector[i] == 0) || ((vector[i] 0))){
     nullstelle[z] = i;
     z++;
    }






> Das ganze funktioniert auch, dauert nur extrem lange (ca. 20  
> Minuten). Gibt es eine Möglichkeit meinen Code zu optimieren  
> bzw. die Nullstellen irgendwie anders schneller zu finden?


Du kannst immer probiere zu parallelisieren und das ganze auf zwei CPUs oder gleich zwei Rechner laufen zu lassen.

Aber mal ehrlich, 20 minuten für ein paar popelige Millionen an Elementen scheint mir wirklich viel zu viel - bist du dir sicher, dass die Schleife da oben der Flaschenhals ist? Üblicherweise ist bei sowas I/O das langsamste, nicht das eigentliche Durchlaufen der Daten.

Grüße,
Moritz

Hallo,

Bisher benutze ich dafür den folgenden C++ Code:

for i = 1 :frowning:length(vektor)-1)
if (vektor(i) == 0)
nullstelle(z) = i;
z = z+1;
elseif ((vektor(i) 0))
nullstelle(z) = i;
z = z+1;
elseif ((vektor(i) > 0) & (vektor(i+1)

Wurde mit MatLab programmiert, …
Ähm, ja… ist mit Matlab programmiert worden.
Ich dachte das würde auf C++ basieren.

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo,

Ähm, ja… ist mit Matlab programmiert worden.
Ich dachte das würde auf C++ basieren.

Die Programmiersprache zumindest nicht.

Die offensichtliche Optimierung ist dann, das ganze stattdessen in C oder C++ zu machen, das ist einfach ein bisschen schneller.

Ich habe mal sowas ähnliches als Beispiel in C geschrieben, das 2 Mio Arrayelemete zufällig füllt und dann die Nullstellen zählt:

#include 
#include 

int main(int argc, char\*\* argv){
 int size = 2000000;
 signed char \*v = malloc(sizeof(char) \* size);
 srand(0);
 /\* initialisiere mit zufällligen Daten \*/
 for (int i = 0; i 0))){
 z++;
 }
 }
 printf("Habe %d Nullstellen gefunden\n", z);

 return 0;
}

Das habe ich ohne Optimierungen kompiliert, und das hat auf meinem Rechner unter 0.1 Sekunden gebraucht auszuführen.

Ich habe schon früher schlechte Erfahrungen mit der Performance von Matlab-Programmen bei großen Datensätzen gemacht. Durch das neuschreiben in C hat sich die Laufzeit eines Programms von über 45min auf unter 2min verbessert.

Ich habe auch mal gelesen, dass es eine Option gibt, matlab-Code nach C zu kompilieren - vielleicht hilft dir das auch weiter.

Soltlest du matlab-spezifische Fragen haben, stelle sie bitte im Brett „Javascript und Scriptsprachen allgemein“.

Grüße,
Moritz

Hallo

Ähm, ja… ist mit Matlab programmiert worden.
Ich dachte das würde auf C++ basieren.

for i = 1 :frowning:length(vektor)-1)
if (vektor(i) == 0)
nullstelle(z) = i;

Was sind das für Daten in vektor()? Ganzzahlen,
Gleitkomma? OK, nach nullstelle() müssen sicher
Integer-Zahlen (Indices).

Willst Du da daraus ein C+±Programm gemacht haben?
Erzähl’ doch mal eine Geschichte zu einer Frage :wink:

Grüße

CMБ

Ähm, ja… ist mit Matlab programmiert worden.
Ich dachte das würde auf C++ basieren.

OK, mußt Du das in Matlab machen oder kannst Du
das auch „extern“ durchführen? Wie Moritz schon
erklärt hat, ist es zwar in Matlab möglich,
C+±Kompilate zu verwenden, dies ist aber um-
ständlich.
z.B.: http://www.ifp.uiuc.edu/~nakazato/mathlib.html

Da Moritz schon ein Programm geliefert hat,
hab ich das natürlich auch mal versucht :wink:
Bei einer cos()-Funktion aus 10,000,000 Werten
mit 1,000 Halbperioden braucht folgendes Programm
(g++, -O3) auf einem alten 2,6GHz P4 ca. 1.1 Sekunden,
wobei die meiste Zeit für die Erzeugung des Datenfeldes
draufgeht. Das Finden der 1,000 Nulldurchgänge fällt
da faktisch nicht ins Gewicht.

Grüße

CMБ

#include 
#include 
#include 
#include 

using namespace std;

 int nullstellen(vector& nullstelle, const vector& vektor)
{
 vector::const\_iterator p;

 for(p=vektor.begin()+1; pnullstelle;
 vectorvektor;
 int L=10000000, N=1000; // erzeuge funkion mit L Punkten und N Nullstellen

 for(int i=0; i

Vielen Dank euch beiden!
Vielen Dank. Habt mir sehr weitergeholfen.

Sind Gleitkommazahlen.

Eigentlich wollte ich ja beim reinen Matlab bleiben, aber wenn man es damit nicht wesentlich schneller hinbekommt, werde ich wohl mal euren C++ Tipp versuchen.

Die Lösung des Problems…
Der folgende Code läuft unter MatLab und benötigt kein C/C++


null_1 = find(sign(vektor(1:end-1)) ~= sign(vektor(2:end)));
null_2 = find(vektor==0);

nullstellen=[null_1 null_2];

Hat bei mir dann nur noch 0,9 sec. benötigt. Wie ihr schon gesagt habt, ist MatLab nur bei vektorisierter Schreibweise schnell… das mit der FOR- Schleife und der IF-Abfrage dauert ewig unter Matlab.

Vielen Dank für eure Tipps!

Hallo Timo,

Der folgende Code läuft unter MatLab und benötigt kein C/C++

null_1 = find(sign(vektor(1:end-1)) ~= sign(vektor(2:end)));
null_2 = find(vektor==0);

nullstellen=[null_1 null_2];

Hat bei mir dann nur noch 0,9 sec. benötigt.

Das ist ja toll. So kommt es dann raus, daß die
„Experten“ hier keine Ahnung von Matlab haben :wink:

Grüße & Danke für die Matlab-Info

CMБ