Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: SCL und Zykluszeitproblem

  1. #1
    Anonymous Gast

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo,

    habe ein Problem mit der Zykluszeit bei folgendem Code:

    Code:
    FOR i:=1  TO DINT_TO_INT(TRUNC(n)) DO
      v:= v + x ** n;
      s:= s + v * a;
    END_FOR;
    Ich habe sechs dieser For-Schleifen in einem Baustein und die scheinen die Zykluszeit nach unten zu reißen. (ca. 120ms)
    Zum testen hab ich mal drei der Schleifen auskommentiert, wobei die Zykluszeit sich dann um die Hälfte verringert.
    Ich kann mir nicht vorstellen, das diese Anweisung die Laufzeit so stark beeinfußt?

    Lässt sich diese Anweisung irgendwie optimieren, abgesehen von dem "DINT_TO_INT(TRUNC...)"

    Fast vergessen: n ist ca. 50

    mfg
    marco
    Zitieren Zitieren Gelöst: SCL und Zykluszeitproblem  

  2. "
    Zitat Zitat von Anonymous
    jetzt kann ich nicht mehr ganz folgen
    Tayloreihe ist bekannt? Ohne Garantie auf Richtigkeit:
    exp(x)=x+1/2*x**2+1/(2*3)*x**3+1/(2*3*4)*x**4+...+1/n!*x**n
    Etwas ähnliches gibt es für ln(x).
    Da es unendlich viele Summanden sind, die aber immer kleiner werden, kann man die ersten berechnen und alle weglassen, deren Beitrag bei einer gegebenen Rechengenauigkeit verschwindet.
    Ich habe einfach geschätzt, daß man in beideen Reihen die ersten acht Summanden braucht. Da man jeden berechnen kann in dem man den vorigen mit x malnimmt und durch n teilt, kommt man für jeden weiteren mit einer zusätzlichen Multiplikation und einer Addition aus.
    Daher die Schätzung von je 16 für exp(n*ln(x))."


  3. #2
    Registriert seit
    26.07.2004
    Beiträge
    87
    Danke
    0
    Erhielt 2 Danke für 2 Beiträge

    Standard

    Könnte schon sein das die Schleifen mächtig auf Zykluszeit gehen. Hast ja selbst schon denn Beweis erbracht. Um die hohe Zykluszeit zu umgehen wäre denkbar die Berechnungen aufzuteilen und nur bei Bedarf zu durchlaufen.

    Gruß

  4. #3
    Registriert seit
    06.10.2003
    Beiträge
    3.403
    Danke
    447
    Erhielt 502 Danke für 406 Beiträge

    Standard

    Hallo Marco,

    Das Potenzieren benötigt schon deutlich Ausführungszeit, aber das ist wohl nicht zu umgehen. Ich würde jedoch DINT_TO_INT(TRUNC(n)) ersetzen, wobei der Zeitgewinn gegenüber dem Potenzieren eigentlich vernachlässigt werden kann.

    Code:
    m := DINT_TO_INT(TRUNC(n));
    
    FOR i:=1  TO m DO 
      v:= v + x ** n; 
      s:= s + v * a; 
    END_FOR;
    Gruß, Onkel
    Es gibt viel mehr Leute, die freiwillig aufgeben, als solche, die echt scheitern.
    Henry Ford

  5. #4
    Registriert seit
    19.06.2003
    Beiträge
    2.200
    Danke
    85
    Erhielt 259 Danke für 175 Beiträge

    Standard

    Zitat Zitat von Onkel Dagobert

    Code:
    m := DINT_TO_INT(TRUNC(n));
    
    FOR i:=1  TO m DO 
      v:= v + x ** n; 
      s:= s + v * a; 
    END_FOR;
    Gruß, Onkel
    Ich würde beim Rechengang ansetzen:
    n läuft von 1 bis m. Wenn du eine zusätzliche variable p einführst und schreibst:

    p:=1;
    FOR i:=1 TO m DO
    p:=p*x;
    v:= v + p;
    s:= s + v * a;
    END_FOR;
    Ist P im 1. Durchlauf p=x =x**1;
    im 2. Durchlauf p=x*x =x**2;
    usw.
    und du kannst das potenzieren ganz sparen.
    Mich wundert, daß du immer das gleiche a hast. Sonst würde ich sagen, du willst den Wert eines Polynoms berechnen...

    Da du jedes v mit a malnimmst, bevor du es zur summe zählst, kannst du das auch nachher machen:

    p:=1;
    FOR i:=1 TO m DO
    p:=p*x;
    v:= v + p;
    s:= s + v;
    END_FOR;
    s:=s*a;

  6. #5
    Anonymous Gast

    Standard

    Hallo Zottel,

    Zitat Zitat von Zottel
    Ich würde beim Rechengang ansetzen:
    n läuft von 1 bis m. Wenn du eine zusätzliche variable p einführst und schreibst:

    p:=1;
    FOR i:=1 TO m DO
    p:=p*x;
    v:= v + p;
    s:= s + v * a;
    END_FOR;
    Ist P im 1. Durchlauf p=x =x**1;
    im 2. Durchlauf p=x*x =x**2;
    usw.
    Deine Antwort hat mich auf folgende Idee gebracht:
    Code:
                          1-x^(n+1)
    a * SUMME (für i=0) (-----------) -1
                             1-x
    damit habe ich die Schleife nun ganz weg, und hoffentlich wieder eine normale Zykluszeit (noch nicht getestet)
    Zitat Zitat von Zottel
    Mich wundert, daß du immer das gleiche a hast.
    Da du jedes v mit a malnimmst, bevor du es zur summe zählst, kannst du das auch nachher machen:
    Ja, so einen Mist mache ich öfters

    mfg
    marco

  7. #6
    Registriert seit
    19.06.2003
    Beiträge
    2.200
    Danke
    85
    Erhielt 259 Danke für 175 Beiträge

    Standard

    Zitat Zitat von Anonymous

    Deine Antwort hat mich auf folgende Idee gebracht:
    Code:
                          1-x^(n+1)
    a * SUMME (für i=0) (-----------) -1
                             1-x
    damit habe ich die Schleife nun ganz weg, und hoffentlich wieder eine normale Zykluszeit (noch nicht getestet)
    Verstehe ich jetzt noch nicht. Das heißt, du hast benutzt eine gschlossene Formel für den Wert der Summe? Warum steht da dann: (für i=0) ?
    Ansonsten: Bei Fließkomma (REAL) geshieht da Potenzieren intern wahrscheinlich über:
    x**n = exp(n*ln(x)), wobei die Funktionen exp und ln über ihre Taylorreihen (wikipedia) gebildet werden.
    Ohne zu wissen, wieviel Glieder der Reihe berechnet werden müssen,nehme ich mal 8 an. Das bedeutet, daß 16 Multiplikationen und Additionen für die Berechnung der Potenz gebraucht werden.
    Der Sonderfall, daß n eine ganze Zahl ist, wird nicht extra behandelt. Ohne Floating-Point Hardware ist eine Addition aufwendiger als eine Multiplikation, mit FP-Hardware sollte es egal sein.
    Daher die Schätzung, daß eine einzelne Potenzierung ab N=32 schneller sein könnte als 32 Multiplikationen in einer Schleife.
    Für ganzzahlige n gäbe es noch einige Tricks, die Berechnung von x^n zu verkürzen:
    Für n<=63:
    x2=x*x
    x4=x2*x2
    x8=x4*x2
    x16=x4*x4
    x32=x8*x4
    P=1.0
    if ((n and 32)<>0) then
    P=P*x32
    n=n-32
    endif
    if ((n and 16)<>0) then
    P=P*x16
    n=n-16
    endif
    if ((n and <>0) then
    P=P*x8
    n=n-8
    endif
    if ((n and 4)<>0) then
    P=P*x4
    n=n-4
    endif
    if ((n and 2)<>0) then
    P=P*x2
    n=n-2
    endif
    if ((n and 1)<>0) then
    P=P*x
    n=n-1 // kann man sich sparen
    endif
    Berechnet also x**n mit maximal 11 Gleitkomma-Multiplikationen. Das ist jetzt kein Spezieller SPS-Code. Dort würde man besser n in ein MB schreiben, so daß statt:
    if ((n and 2)<>0)
    U Mx.1

    und statt:
    n=n-2
    R Mx.1

    geschrieben werden könnte.

  8. #7
    Anonymous Gast

    Standard

    Zitat Zitat von Zottel
    Verstehe ich jetzt noch nicht. Das heißt, du hast benutzt eine gschlossene Formel für den Wert der Summe? Warum steht da dann: (für i=0) ?
    Ja genau, ich benutze eine geschlossene Formel zur Berechnung der Summe der Potenzen.

    Ich hab keine Ahnung wie ich hier ein Summenzeichen einfügen soll.
    Mit i=0 meinte ich das n bei 0 anfängt <- ok, blöd ausgedrückt, sorry

    Ansonsten: Bei Fließkomma (REAL) geshieht da Potenzieren intern wahrscheinlich über:
    x**n = exp(n*ln(x)), wobei die Funktionen exp und ln über ihre Taylorreihen (wikipedia) gebildet werden.
    Wenn der SCL-Compiler wieder irgendwie AWL daraus generiert, wird das wohl stimmen.

    Ohne zu wissen, wieviel Glieder der Reihe berechnet werden müssen,nehme ich mal 8 an. Das bedeutet, daß 16 Multiplikationen und Additionen für die Berechnung der Potenz gebraucht werden.
    Der Sonderfall, daß n eine ganze Zahl ist, wird nicht extra behandelt. Ohne Floating-Point Hardware ist eine Addition aufwendiger als eine Multiplikation, mit FP-Hardware sollte es egal sein.
    Daher die Schätzung, daß eine einzelne Potenzierung ab N=32 schneller sein könnte als 32 Multiplikationen in einer Schleife.
    jetzt kann ich nicht mehr ganz folgen

    Für ganzzahlige n gäbe es noch einige Tricks, die Berechnung von x^n zu verkürzen:
    Für n<=63:
    x2=x*x
    x4=x2*x2
    x8=x4*x2
    x16=x4*x4
    x32=x8*x4
    P=1.0
    if ((n and 32)<>0) then
    P=P*x32
    n=n-32
    endif
    if ((n and 16)<>0) then
    P=P*x16
    n=n-16
    endif
    if ((n and <>0) then
    P=P*x8
    n=n-8
    endif
    if ((n and 4)<>0) then
    P=P*x4
    n=n-4
    endif
    if ((n and 2)<>0) then
    P=P*x2
    n=n-2
    endif
    if ((n and 1)<>0) then
    P=P*x
    n=n-1 // kann man sich sparen
    endif
    Berechnet also x**n mit maximal 11 Gleitkomma-Multiplikationen. Das ist jetzt kein Spezieller SPS-Code. Dort würde man besser n in ein MB schreiben, so daß statt:
    if ((n and 2)<>0)
    U Mx.1

    und statt:
    n=n-2
    R Mx.1

    geschrieben werden könnte.
    Ja n fängt bei 1 an und wird inkrementiert, also ganzzahlig.
    Diesen Teil werde ich mir noch mal ganz in Ruhe zu Gemüte führen

    mfg
    marco

  9. #8
    Registriert seit
    27.10.2005
    Ort
    Schwäbisch Gmünd
    Beiträge
    5.224
    Danke
    630
    Erhielt 955 Danke für 769 Beiträge

    Standard

    Bei geschlossenen Formeln kann der konstante Teil über eine LookUp-Tabelle realisiert werden, die einmal berechnet wird. Dies kann dann sogar auf dem PC erfolgen und in einen DB in Quelle eingetragen werden.
    Rainer Hönle
    DELTA LOGIC GmbH

    Ein Computer kann das menschliche Gehirn nicht ersetzen. Engstirnigkeit kann unmöglich simuliert werden. (Gerd W. Heyse)

  10. #9
    Registriert seit
    19.06.2003
    Beiträge
    2.200
    Danke
    85
    Erhielt 259 Danke für 175 Beiträge

    Standard

    Zitat Zitat von Anonymous
    jetzt kann ich nicht mehr ganz folgen
    Tayloreihe ist bekannt? Ohne Garantie auf Richtigkeit:
    exp(x)=x+1/2*x**2+1/(2*3)*x**3+1/(2*3*4)*x**4+...+1/n!*x**n
    Etwas ähnliches gibt es für ln(x).
    Da es unendlich viele Summanden sind, die aber immer kleiner werden, kann man die ersten berechnen und alle weglassen, deren Beitrag bei einer gegebenen Rechengenauigkeit verschwindet.
    Ich habe einfach geschätzt, daß man in beideen Reihen die ersten acht Summanden braucht. Da man jeden berechnen kann in dem man den vorigen mit x malnimmt und durch n teilt, kommt man für jeden weiteren mit einer zusätzlichen Multiplikation und einer Addition aus.
    Daher die Schätzung von je 16 für exp(n*ln(x)).

  11. #10
    Registriert seit
    07.10.2005
    Beiträge
    5
    Danke
    2
    Erhielt 1 Danke für 1 Beitrag

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo Zottel

    jetzt hab ich verstanden wo Du drauf hinaus willst.
    Zitat Zitat von Zottel
    Für ganzzahlige n gäbe es noch einige Tricks, die Berechnung von x^n zu verkürzen:
    Das könnte sogar funktionieren

    1.) Die SPS scheint nicht zu unterscheiden ob der Exponent eine reelle oder natürlische Zahl ist.
    2.) Die Ausführungszeiten der CPU:

    z.B. CPU315
    EXP -> 449us
    *R -> 3,2us
    Da kann ich doch schon einige arithmetische Operationen bearbeiten, bis an die Zeit von "EXP" rankomme

    Allerdings glaube ich, das diese Art der Optimierung für die Praxis nicht besonders relevant ist.

    mfg
    marco

    PS: hab mich mal angemeldet

Ähnliche Themen

  1. Antworten: 14
    Letzter Beitrag: 19.10.2009, 10:44
  2. Zykluszeitproblem mit Beckhoff/Twincat
    Von andimann im Forum CODESYS und IEC61131
    Antworten: 3
    Letzter Beitrag: 09.01.2008, 15:55
  3. "Zykluszeitproblem" / Schnelle Zeitmessung
    Von mr__mines im Forum Programmierstrategien
    Antworten: 35
    Letzter Beitrag: 02.03.2007, 02:57

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •