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

Seite 3 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 21 bis 30 von 32

Thema: Baustein mit INOUT oder Baustein mit Interface?????

  1. #21
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.166
    Danke
    921
    Erhielt 3.286 Danke für 2.655 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Zitat Zitat von Thomas_v2.1 Beitrag anzeigen
    Bei Übergabe eines Zeigers auf eine Struktur, wird in der Funktion nur einmalig ein Register wie ebx mit der Adresse geladen, und die folgenden Anweisungen laufen dann über sowas wie MOV eax, word ptr [ebx+0].
    Wenn mehrere Strukturen über INOUT übergeben werden und schön gemischt zugegriffen wird, dann nützt das Halten der Anfangsadresse einer Struktur wohl eher wenig.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  2. #22
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Zitat Zitat von PN/DP Beitrag anzeigen
    Wenn mehrere Strukturen über INOUT übergeben werden und schön gemischt zugegriffen wird, dann nützt das Halten der Anfangsadresse einer Struktur wohl eher wenig.
    Es gibt aber mehr als nur ein Register. Zumindest wenn Daten zwischen zwei Strukturen ausgetauscht werden sollen, können dazu die Anfangsadressen in den Registern gehalten werden. Klar, irgendwann "kostet" es mehr als die einzelnen Werte zu übergeben, aber wer schreibt (und wartet) eine Funktion mit hunderten Funktionsparametern?

    Außerdem erfolgt auch der Zugriff auf Funktionsparameter in ähnlicher Weise wie auf die Variablen einer Struktur, nämlich per Stack(Base-)pointer plus Offset. D.h. die Funktionsparameter entsprechen so gesehen auch einer Struktur, nur ist der Zeiger auf die Struktur der Funktionsparameter innerhalb einer Funktion im esp-Register gespeichert. Wenn du nur eine einizige Struktur übergibst, macht das darum kaum einen Unterschied.

    Ich weiß aber nicht wie Codesys die In-Out Parameter in Assembler umsetzt. Wenn in C z.B. ein Parameter als Zeiger auf einen Int übergeben wird damit darüber Werte zurückgegeben werden können, muss beim Zugriff auf diesen auch erst die Adresse des Parameters (esp+offset) in ein Register geladen werden, um dann in der nächsten Anweisung indirekt darauf zugreifen zu können.

  3. #23
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.166
    Danke
    921
    Erhielt 3.286 Danke für 2.655 Beiträge

    Standard

    Wie der Zugriff auf die Übergabeparameter im Detail erfolgt ist für den Performance-Vergleich "Struktur-Übergabe per IN vs. INOUT" erstmal zweitrangig, weil der bei beiden Varianten ja gleich erfolgt. Fakt ist aber, daß
    • bei Übergabe per IN (byValue) liefert das Lesen des Übergabeparameters bereits den Wert der außen angeschalteten Variable
    • bei Übergabe per INOUT (byRef) liefert das Lesen des Übergabeparameters zunächst nur die Referenz auf die Variable
      --> es muß ein weiteres Mal auf den Speicher zugegriffen werden. Das geht unmöglich zusammen in nur 1 Takt. (dieser weitere Zugriff geht auf unvorhersehbare Adressen, meist in Speicher außerhalb des Stack)

    Weil bei Siemens S7 bei byRef keine Adresse übergeben wird sondern ein zusammengesetzter POINTER, gestaltet sich der weitere Zugriff auf die referenzierte Variable relativ aufwendig. Ich habe keine Ahnung, ob bei Codesys eine Flat-Adresse übergeben wird oder vielleicht ebenfalls etwas ähnliches wie Bereichsselektor + Offset?

    Ich kann mir vorstellen, daß die Übergabe von Referenzen via INOUT Performance-Vorteile beim Durchreichen durch mehrere Bausteinaufrufe hätte, falls das überhaupt geht (bei Siemens S7 geht es nicht), doch bei SPS-Programmen ist die Schachtelungstiefe meist nicht groß.

    • Für den Aufrufer ist es natürlich effizienter, einfach nur eine Referenz auf eine Stuktur zu übergeben, als die Struktur zu kopieren. Doch macht das den Mehraufwand beim Parameter-Lesen wett?


    Für den Vergleich der Performance von Struktur-Übergabe per IN vs. INOUT habe ich ein Testprogramm in SCL erstellt:
    Code:
    TYPE Type1
      STRUCT
        a : REAL;
        b : REAL;
        c : REAL;
        d : REAL;
        e : REAL;
        f : REAL;
      END_STRUCT
    END_TYPE
    
    //*** aufgerufene Function ***********************
    FUNCTION FC_foo : REAL
    VAR_INPUT
    //VAR_IN_OUT
      s1 : Type1;
      s2 : Type1;
    END_VAR
    
      FC_foo:=(s1.a*s1.b+s2.a*s2.b) + (s1.c*s2.c+s1.d*s2.d) + (s1.e+s2.e)*2.0 - (s1.a*s1.f+s2.a*s2.f);
    END_FUNCTION
    
    //*** aufgerufener Function_Block ****************
    FUNCTION_BLOCK FB_foo
    VAR_INPUT
    //VAR_IN_OUT
      s1 : Type1;
      s2 : Type1;
    END_VAR
    VAR_OUTPUT
      out : REAL;
    END_VAR
    
      out:=(s1.a*s1.b+s2.a*s2.b) + (s1.c*s2.c+s1.d*s2.d) + (s1.e+s2.e)*2.0 - (s1.a*s1.f+s2.a*s2.f);
    END_FUNCTION_BLOCK
    
    //*** aufrufender FUNCTION_BLOCK *****************
    FUNCTION_BLOCK FB_caller
    VAR
      Result : REAL;
      S1 : Type1;
      Instanz1 : FB_foo;
      S2 : Type1;
      Instanz2 : FB_foo;
    END_VAR
    
    (* Aufruf FC ... *)
    //  Result:=FC_foo(s1:=S1, s2:=S2);
    
    (* ... oder FB *)
      Instanz2(s1:=S1, s2:=S2);
      Result:=Instanz2.out;
    END_FUNCTION_BLOCK
    Ergebnis mit SCL-Compiler V5.3 für S7-300/400:
    Code:
    Codegröße bei        FB_caller  FB_foo  | FB_caller  FC_foo
    Übergabe VAR_INPUT  :   166      216    |    122      474
    Übergabe VAR_IN_OUT :   106      436    |    122      474
    Änderung Codegröße  :  - 60    + 220    |      0        0 (*)
    
    (*) FC: Übergabe zusammengesetzter Datentypen erfolgt immer per POINTER
    Man sieht, daß bei S7 die Codegröße (und ziemlich wahrscheinlich auch die Ausführungszeit) bei Übergabe per VAR_IN_OUT insgesamt ansteigt - also die Performance schlechter als bei Übergabe per VAR_INPUT ist.
    (dabei benutzt der SCL-Compiler noch nichtmal BLKMOV oder memcpy, um die Strukturen in VAR_INPUT zu kopieren, sondern kopiert in 4-Byte-Häppchen)

    Jetzt interessiert mich natürlich, wie das auf einem Codesys-System aussieht. Leider habe ich kein Codesys zur Verfügung. Vielleicht kann mal jemand den Vergleich machen und berichten?

    Interessant wäre auch wie der Vergleich für die S7-1500 und die S7-1200 mit "optimiertem" und "Standard"-Speicherzugriff ausfällt.



    "Nebenkriegsschauplatz":
    Wegen der mehrfachen Verwendung von s1.a und s2.a in FC_foo und FB_foo MÜSSTEN diese Werte bei Übergabe per Referenz vor Verwendung zuerst lokal/temporär zwischengespeichert werden um Multitasking-Konsistenzprobleme zu vermeiden!
    Z.B. ein Regler in der OB35-Task schreibt direkt in eine globale Struktur (in S1.a oder S2.a), welche in der OB1-Task an einen FC oder per IN_OUT an FB übergeben wird --> wenn der OB35 den FC/FB unterbricht, dann kann es zu fehlerhaften Berechnungen kommen, weil mit Werten von vor der Unterbrechung und eventuell geänderten Werten von nach der Unterbrechung gerechnet wird. Der SCL-Compiler berücksichtigt dieses Problem nicht, man muß selber dafür sorgen, daß nicht in verschiedenen Task auf die Struktur geschrieben wird. Ggf. muß man selber zuerst für das Umkopieren auf lokalen Speicher sorgen.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  4. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Ralle (08.12.2015)

  5. #24
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Ich kann morgen mal bei Codesys nachsehen wie In-Out umgesetzt wird, hab zwar schon ein paar fertige "Assemblate" aber nichts mit In-Out Parametern

    Ich persönlich würde mir bei Codesys darüber so gut wie keine Gedanken machen.
    Außer bei Siemens S7 verwende ich eine Struktur wenn ich eine Struktur benötige, einen Parameter per Value wenn ich es benötige, und einen Zeiger ich einen Zeiger benötige. Nur bei Siemens programmiert man nicht wie es am elegantesten ist, sondern damit es dieses kaputte Siemens-Konzept aus S5-Zeiten, die langsamen CPUs und in den beschnitteten Speicher passt. Und dieses Prinzip wurde bei der 1200/1500 weitergeführt, wo alles ohne triftigen Grund irgendwie anders sein muss, und wenn man nicht aufpasst anstatt mit einem ICE mit der Bimmelbahn unterwegs ist.

    Wie heißt es so schön von Donalt Knuth: "Premature optimization is the root of all evil".
    Solange ich in der SPS kein Numbercrunching veranstalten will, programmiere ich so wie es am elegantesten ist....außer bei Siemens eben.

  6. Folgende 2 Benutzer sagen Danke zu Thomas_v2.1 für den nützlichen Beitrag:

    Ralle (08.12.2015),rostiger Nagel (08.12.2015)

  7. #25
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.715
    Danke
    398
    Erhielt 2.398 Danke für 1.998 Beiträge

    Standard

    ... das ist möglicherweise dem Umstand geschuldet, dass bei CodeSys und Konsorten eventuell nur noch mit Referenzen gearbeitet wird.
    In dem Fall würde eine Struktur tatsächlich für den Rechner keinen Mehr-Aufwand bedeuten ...

    Gruß
    Larry

  8. #26
    Registriert seit
    30.08.2005
    Beiträge
    280
    Danke
    41
    Erhielt 96 Danke für 66 Beiträge

    Standard

    Dann wollen wir doch mal ein bisschen Licht ins Dunkel bringen:

    Ein VAR_IN_OUT ist in CODESYS einfach realisiert als POINTER auf die übergebenen Daten. Der Zugriff darauf benötigt eine Dereferenzierung
    mehr als der direkte Zugriff.
    Bei VAR_INPUT wird der Wert kopiert.
    Will man unabsichtliches verändern des übergebenen Wertes verhindern, dann kann man VAR_IN_OUT CONSTANT verwenden
    (seit Version 3.5.2.0). Auf so eine Variable darf nicht geschrieben werden.

    Wenn man eine Struktur (oder FB oder STRING) an eine Funktion (oder FB) übergibt, dann ist es in aller Regel sinnvoll, das per VAR_IN_OUT zu tun.
    Der Aufruf geht viel schneller und der Zugriff auf die Struktur per VAR_IN_OUT ist kaum langsamer.
    Allenfalls wenn immer alle Werte einer Struktur verarbeitet werden und vielleicht sogar mehrfach darauf zugegriffen wird
    könnte es vorteilhaft sein die Struktur zu kopieren. Der Speicherverbrauch ist in jedem Fall höher.

    Ein Interface ist vermutlich nicht sinnvoll, wenn man nur den Zugriff auf Daten bieten will. Der Zugriff auf eine Eigenschaft eines Interfaces
    entspricht immer einem Funktionsaufruf und ist dementsprechend deutlich langsamer als der Zugriff auf ein Strukturelement.
    Interfaces sollte man dann verwenden wenn man Code schreibt, der verschieden implementierte FB's verwendet, die gemeinsame Eigenschaften haben.
    Ein Beispiel habe ich schon mal in diesem Thread beschrieben:

    http://www.sps-forum.de/codesys-und-iec61131/69842-codesys-objektorientiertes-programmieren.html


    Ich finde es vor allem dann sehr sinnvoll, mit Interfaces zu arbeiten, wenn man Bibliotheken schreibt.
    Viele unserer Kunden entwickeln ganze Bibliothekslandschaften und da kann es sehr sinnvoll sein, dass die Bibliotheken mit gemeinsamen
    Interfaces arbeiten.
    Überhaupt muss man feststellen dass sich die ganze Power der Objektorientierung an einem einzelnen Projekt oft nicht gut darstellen lässt.
    Die Vorteile kommen zum Tragen wenn man weiterentwickelt, Varianten produziert, standardisierte Abläufe hat, wenn Teams an Projekten
    arbeiten und wenn Teams an Bibliotheken arbeiten.
    Bernhard Werner
    3S-Smart Software Solutions (CODESYS)

  9. Folgende 2 Benutzer sagen Danke zu Werner29 für den nützlichen Beitrag:

    Larry Laffer (08.12.2015),Thomas_v2.1 (08.12.2015)

  10. #27
    Registriert seit
    16.12.2015
    Ort
    Innsbruck
    Beiträge
    32
    Danke
    11
    Erhielt 6 Danke für 6 Beiträge

    Standard

    Wobei ob schneller oder langsamer ist vermutlich nicht die Frage, sondern eigentlich was ist schöner.

    Beim Thema Geschwindigkeit ist nur wichtig: Sobald man anfängt mit objektorientierter Programmierung muss man aufpassen, dass Variablen die nicht statisch angelegt sind sondern am Stack liegen möglichst zu vermeiden.

    Beispiel: Du hast einen Baustein mit seinen Eigenschaften (im VAR Bereich des FBs) und zugehörige Methoden, welche diese Eigenschaften für irgendwelche Abläufe verwenden. dann kann es passieren dass diese Methoden zyklisch aufgerufen werden. Wenn du nun im VAR Bereich der Methode einen String (zb. für eine Fehlermeldung) anlegst, dann wird diese Variable mit jedem Aufruf am Stack angelegt, mit 0 gelöscht und anschließend verwendet. Das sind dann bei einem STRING(200) mit jedem Durchlauf 200 Bytes löschen. Früher war diese Fehlervariable im statischen Bereich des Bausteins und somit gabs kein Problem.

    Wir haben uns intern in der Firma zusammengetan und für den Umstieg auf objektorientiertes Programmieren ein paar Bücher zu Gemüte geführt. Wenn man sich nun an die üblich propagierten Patterns hält kann man hier enorm profitieren.

    Als Beispiel haben wir uns einen Logging Mechanismus gebaut => hier wurde die Art und weiße wie Meldungen abgespeichert und exportiert werden komplett über Dependency Injection Pattern getrennt. Das heißt die Meldungen werden von einem Baustein abgespeichert (der schaut für den Programmierer immer gleich aus) und dieser bekommt einen anderen "eingepflanzt" welcher die Daten exportiert. Wobei hier kann gewählt werden ob in eine Datei oder in eine Datenbank oder über die serielle Schnittstelle raus exportiert wird.

    Falls hier nicht das nötige KnowHow vorhanden ist, sollte man beim Umstieg evtl. auf einen Software Architekten hören, da spart man sich viel Ärger!

    lg seehma

  11. #28
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Zitat Zitat von seehma Beitrag anzeigen
    Wenn du nun im VAR Bereich der Methode einen String (zb. für eine Fehlermeldung) anlegst, dann wird diese Variable mit jedem Aufruf am Stack angelegt, mit 0 gelöscht und anschließend verwendet. Das sind dann bei einem STRING(200) mit jedem Durchlauf 200 Bytes löschen.
    Hast du nachgesehen ob das wirklich so umgesetzt ist?
    Dann müsste im IEC-Standard definiert sein, dass alle Bytes genullt werden müssen. Ist das dort nicht festgelegt, würde ich persönlich - wäre ich Compilerbauer - nur die Aktuallänge auf Null setzen.

  12. #29
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Als Zusatz:
    Bei einem FB ist es gar nicht möglich bei jedem Aufruf die Werte auf Null zu setzen, denn es ist ja gerade die Eigenschaft eines FB dass die Werte im Var-Bereich statisch sind. Also wenn da etwas genullt wird, dann nur einmalig.

  13. #30
    Registriert seit
    16.12.2015
    Ort
    Innsbruck
    Beiträge
    32
    Danke
    11
    Erhielt 6 Danke für 6 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Also im Standard hab ich nicht nachgesehen (hab den leider nicht, bekommt man den woher?), aber wir haben es gemessen und sind dann in der Doku auf das 'no initialize' attribut gekommen. Bei einem FB (jetzt Object) im VAR Bereich wird nur beim Start einer SPS alles mit 0 initialisiert (static eben).

    Anfangs hatten wir das Problem mit der Initialisierung massiv. Wenn man ein paar hundert Methoden hat und in jeder werden am Stack solche Fehler-Strings angelegt, löscht man zyklisch 20000Bytes -> das dauert.

    Wie gesagt bei kleineren Projekten (je nach notwendiger Zykluszeit) kein Problem. Wenn es mal ein paar tausend Methoden sind dann kann dies schnell zu einem Laufzeit Problem führen.

    Lg

Ähnliche Themen

  1. Schützüberwachung mit Baustein SF_EDM
    Von bernd81 im Forum CODESYS und IEC61131
    Antworten: 3
    Letzter Beitrag: 27.09.2013, 13:36
  2. Baustein mit IN & OUT Paramtern, oder INOUT`erstellen?
    Von Bensen83 im Forum CODESYS und IEC61131
    Antworten: 13
    Letzter Beitrag: 23.11.2012, 13:08
  3. Codeübergabe am FB Baustein mit SCL
    Von Blackforest im Forum Simatic
    Antworten: 13
    Letzter Beitrag: 02.01.2009, 17:57
  4. Baustein mit SCL programmieren
    Von mr_spooner im Forum Simatic
    Antworten: 10
    Letzter Beitrag: 20.11.2008, 09:19
  5. Zählerfunktion mit einem DB Baustein
    Von Irocke im Forum Simatic
    Antworten: 6
    Letzter Beitrag: 31.01.2008, 15:03

Lesezeichen

Berechtigungen

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