# was bringt gleichzeigtiger Zugriff auf viele S7 ?



## Fliegertiger (15 Januar 2010)

Hi,

ich Frage mich ob der gleichzeitige Zugriff auf meherern S7 mittels Threading eine höhere Performance bringt als sequenzieller Zugriff (eine S7 nach der anderen)?

 Hintergrund: es solle der ganze Inhalt von mehreren Datenbausteinen pro S7 ausgelesen werden.

Hier im Forum hab ich gelesen daß die Funktionen von LibnoDave nur jeweils von einem Thread gleichzeitig aufgerufen werden dürfen.

Hat dann der gleichzeitige Zugriff überhaupt Vorteile?

Gruß Fliegertiger


----------



## Rainer Hönle (15 Januar 2010)

Selbstverständlich bringt der parallele Zugriff auf mehrere Steuerungen Vorteile. Wenn man davon ausgeht, dass alle Steuerungen gleich schnell antworten, dann benötigt man bei sequentiellem Zugriff fast steuerungsanzahl-soviel Zeit wie bei parallelem Zugriff. Hängt natürlich vom verwendeten Adapter ab. Beim PC-Adapter gilt das nicht ganz, bei TCP/IP schon eher.


----------



## Fliegertiger (15 Januar 2010)

Hm, verstehe ich das dann richtig wenn ich mir vorstelle, daß immer nur ein Thread die Funktion 'readBytes' der LibNoDave ausführen kann?

Das hätte dann doch zur Folge, daß auch nur nacheinander von den SPSén gelesen werden kann, oder?

Gruß Fliegertiger


----------



## Rainer Hönle (15 Januar 2010)

Fliegertiger schrieb:


> Hm, verstehe ich das dann richtig wenn ich mir vorstelle, daß immer nur ein Thread die Funktion 'readBytes' der LibNoDave ausführen kann?


Steht das so in der libnodave-Anleitung?



> Das hätte dann doch zur Folge, daß auch nur nacheinander von den SPSén gelesen werden kann, oder?


Richtig, das wäre dann wieder sequentiell.

Wie das in libnodave implementiert ist, weiß ich nicht. In AGLink habe ichdas so gemacht, dass die Funktionen threadsicher sind und somit von vielen Threads aufgerufen werden können, dass diese auch asynchron (ohne warten auf Funktionsende) aufgerufen werden könnnen und eine Benachrichtung bei Funktionsende schicken. Und da ist es so, dass die komplette Kommunikation zu den SPSen parallesisiert wird und entsprechend schneller abläuft als wenn diese sequentiell durchgeführt wird.


----------



## MW (15 Januar 2010)

Fliegertiger schrieb:


> Hm, verstehe ich das dann richtig wenn ich mir vorstelle, daß immer nur ein Thread die Funktion 'readBytes' der LibNoDave ausführen kann?



Ich nutze Libnodave auch in mehreren Threads gleichzeitig, bis dato hab ich da noch kein Problem festgestellt. Ich kann allerdings nicht sicher sagen, ob Libnodave wirklich Threadsicher ist. 

Man muss halt nur aufpassen damit man den Funktionen die richtigen Parameter übergibt, damit man nicht aufeinmal auf der falschen SPS landet, isn schöner flüchtigkeitsfehler.


----------



## Rainer Hönle (16 Januar 2010)

Das ist schon einmal ein gutes Zeichen. Die Frage ist, verwendet libnodave globale Daten, auf die ohne Verriegelung zugegriffen wird?


----------



## beta (16 Januar 2010)

Hallo,
ich hatte vor einiger Zeit genau dieses Problem. Beim mehrfachen Zugriff aus mehreren Threads bekam ich Probleme. Besonders wenn es sehr schnelle Zugriffe waren. Ich kann mich da an sporadische nicht nachvollziehbare Lesefehler und hochlaufenden Speicher erinnern die aber erst nach einiger Zeit auftauchten. Nach der Umstellung auf serielle Abfragen hatte es sich meiner Ansicht nach erledigt. Ist aber auch schon alles etwas her, Versuch macht klug. Ich hatte es aber auch schon irgendwo gelesen, dass man lieber seriell abarbeiten sollte.
beta


----------



## Thomas_v2.1 (16 Januar 2010)

Libnodave macht ausgiebig Verwendung von malloc(), und da ist es Sache des Compilers ob die Funktion Thread-sicher ist oder eben nicht.

Unter Linux ist malloc() mit dem gcc imho threadsafe. Stellt sich nur die Frage mit welchen Compiler die mitgelieferte dll übersetzt wurde.
Der Microsoft VC braucht dazu wohl eine extra Option beim übersetzen. Im Makefile.vc habe ich dazu aber gerade auf die Schnelle nichts gefunden.


----------



## Rainer Hönle (16 Januar 2010)

Thomas_v2.1 schrieb:


> Libnodave macht ausgiebig Verwendung von malloc(), und da ist es Sache des Compilers ob die Funktion Thread-sicher ist oder eben nicht.
> 
> Unter Linux ist malloc() mit dem gcc imho threadsafe. Stellt sich nur die Frage mit welchen Compiler die mitgelieferte dll übersetzt wurde.
> Der Microsoft VC braucht dazu wohl eine extra Option beim übersetzen. Im Makefile.vc habe ich dazu aber gerade auf die Schnelle nichts gefunden.


Bei BilliSoft stellt man im Projekt ein, ob man die single- oder multithreaded Bibliotheken verwenden will. Das Makefile-Äquivalent dafür sollte /MT (statische Lib) oder /MD (dynamische Lib), bzw. /MTd oder /MDd für die Debugvariante sein.


----------



## Thomas_v2.1 (16 Januar 2010)

Rainer Hönle schrieb:


> Bei BilliSoft stellt man im Projekt ein, ob man die single- oder multithreaded Bibliotheken verwenden will. Das Makefile-Äquivalent dafür sollte /MT (statische Lib) oder /MD (dynamische Lib), bzw. /MTd oder /MDd für die Debugvariante sein.



Also dann ist libnodave in der mitgelieferten Version nicht für mehrere Threads geeignet, wenn man davon ausgeht dass es mit VC übersetzt wurde.

Aber wers braucht kann die Optionen ja nachlegen und neu übersetzen ;-)

http://msdn.microsoft.com/de-de/library/2kzt1wy3(VS.80).aspx


----------



## Rainer Hönle (16 Januar 2010)

Dann ist zumindest die threadsichere Runtime des Compilers dabei und ein Problem beseitigt. Dann ist aber immer noch die Frage, ob libnodave auf globale Daten ohne entsprechende Verriegelung zugreift.


----------



## Ralle (16 Januar 2010)

Mal unabhängig von der Threadsicherheit libbnodaves, hab ich es mit Grafikfunktionen und Delphi 7 auch schon geschafft, daß eine Multithreadapplikation langsamer lief, als eine, in einem Thread ablaufende Applikation. Die Frage ist, inwieweit das Ganze wirklich parallelisierbar ist und ob die Entwicklungsbibliothek (hier VCL von Delphi 7) auch wirklich selbst optimal dafür geeignet ist. Letztlich kann man die Daten von den S7 ja parallel anfragen, aber entgegennehmen und verarbeiten muß sie die erstellte Applikation und wie effektiv das dann tatsächlich ist, kann man nicht so wirklich vorhersagen. Deswegen wäre ich bei Rainers aussage etwas vorsichtig.


----------



## Rainer Hönle (17 Januar 2010)

Es geht mir hier nur um die Kommunikationsgeschwindigkeit, nicht um die Vererabeitung danach. Bei Kommunikation wird die meiste Zeit auf die Antwort der Steuerung gewartet. Und in dieser Zeit können andere Steuerung gefragt werden.


----------



## Question_mark (17 Januar 2010)

*Habe das Problem nicht wirklich verstanden ...*

Hallo,

ich habe bei eurem Anliegen zur parallelen, threadgesteuerten Kommunikation zu einer SPS von einem PC doch ein gewaltiges Verständnisproblem...

Wenn ich die Kommunikation zu beliebig vielen SPS mittels Treiber über einen (!!!) z.B. NIC anstosse, wie zum Teufel soll ich das parallel hinkriegen ??

Es wird immer seriell bleiben, da könnt Ihr machen was Ihr wollt 

Gruß

Question_mark


----------



## Thomas_v2.1 (17 Januar 2010)

Question_mark schrieb:


> Wenn ich die Kommunikation zu beliebig vielen SPS mittels Treiber über einen (!!!) z.B. NIC anstosse, wie zum Teufel soll ich das parallel hinkriegen ??
> 
> Es wird immer seriell bleiben, da könnt Ihr machen was Ihr wollt


Es ist aber ein Unterschied, ob ich zu 100 SPS eine einzige Verbindung aufbaue, oder 100 Verbindungen aufbaue.

Im zweiten Fall starte ich 100 Threads, diese schicken jeweils eine Anfrage an die SPS und legen sich daraufhin schlafen bis das Ergebnis zurückkommt. Wenn die letzte Anfrage raus ist, ist ja vielleicht die erste SPS schon mit der Antwort fertig.


----------



## Question_mark (17 Januar 2010)

*Parallelverarbeitung ist was anderes ....*

Hallo,



			
				Thomas_v2.1 schrieb:
			
		

> Wenn die letzte Anfrage raus ist, ist ja vielleicht die erste SPS schon mit der Antwort fertig.



Aber was zum Teufel hat das mit einer parallelen Verarbeitung zu tun ???
Die Anfragen werden seriell gesendet und die Antworten kommen immer noch seriell zurück.

Der Flaschenhals ist z.B. der einzige NIC-Adapter im PC, da bekommst Du nun mal nur einzige Kommunikation zu einer (!!!) SPS gleichzeitig zustande. Egal wieviel im PC gleichzeitig abgearbeitet wird, es muss über den NIC raus ..

Gruß


----------



## Thomas_v2.1 (17 Januar 2010)

Kann sein dass du vielleicht eine andere Kommunikationsbibliothek meinst.

Bei libnodave wird mir bei einer Verbindung auch nur ein Socket zu einer SPS aufgebaut. D.h.:
Verbindungskanal (z.B. Socket) öffnen -> Verbindung zur SPS aufbauen -> Daten anfragen -> Daten empfangen

Die Zeit die die SPS zum Antworten braucht kann das Programm nichts machen außer warten. Wie Rainer oben schon schrieb, geht die meiste Zeit mit warten auf die Antwort der SPS drauf.
Wenn ich mehrere Threads starte, kann ich in der Wartezeit mit anderen SPSen kommunizieren die gerade frei sind.


----------



## Zottel (18 Januar 2010)

Libnodave verwendet malloc() im einfachsten Fall nur innerhalb von daveNewInterface() und daveNewConnection(). Diese Funktionen sollten nach meiner Intention nur einmal pro benutzter Schnittstelle/Socket bzw. Pro SPS aufgerufen werden.
Im laufenden Betrieb ist die einzige globale Variable daveDebug. Auf daveDebug wird normalerweise nur lesend zugegriffen, daher sind konkurrierende Schreibzugriffe nicht zu erwarten. Ferner sollte in Anwendungen daveDebug=0 sein.
Die einzige Konsequenz ist also, daß, sobald ein Thread daveDebug <>0 setzt, alle Threads Debugging-Informationen schreiben werden.

Was nicht geht ist, daß mehrere Threads eine Verbindung zur SPS teilen. Da Libnodave zeichenweise sendet, könnte eine Anfrage an die SPS von einer weiteren an beliebiger Stelle unterbrochen werden. Das Ergebnis wäre wohl Blödsinn für die SPS.
Weiterhin ist mir nicht bekannt was eine S7 macht, wenn eine weitere Anfrage eingeht, bevor die erste beantwortet wurde.
Schließlich ist unbekannt, ob die Anfragen in der Reihenfolge ihres Eingangs beantwortet würden. Egal ob ja oder nein, jeder Thread könnte die Antwort auf Anfragen eines anderen erhalten.

Wer Threads braucht, sollte wissen wozu:
1. Um mehrere SPS über Ethernet anzusprechen: Pro SPS ein socket, ein daveInterface und ein daveConnection struct.
2. Um mehrere SPS an MPI über denselben seriell/MPI-Adapter anzusprechen.
3. Um dieselbe SPS von mehreren Clients/Programmen/Standorten anzusprechen.

Im Fall 2 und 3 ist es ratsam, einen Prozess/Thread laufen zu lassen, der mit der Steuerung spricht und Daten an die weiteren Threads/Prozesse weiterreicht. Dieser Prozeß entspricht dann gewissermaßen einem OPC-Server.


----------



## Question_mark (18 Januar 2010)

*Parallel ist was anderes*

Hallo,



			
				Thomas_v2.1 schrieb:
			
		

> Bei libnodave wird mir bei einer Verbindung auch nur ein Socket zu einer SPS aufgebaut. D.h.:
> Verbindungskanal (z.B. Socket) öffnen -> Verbindung zur SPS aufbauen -> Daten anfragen -> Daten empfangen



Aber das ist nicht so wirklich eine Parallelverarbeitung, oder ???



			
				Thomas_v2.1 schrieb:
			
		

> ]Wenn ich mehrere Threads starte, kann ich in der Wartezeit mit anderen SPSen kommunizieren die gerade frei sind.



Ja, das kannst Du schon.. Aber niemals parallel, mich stört hier einfach der Begriff "Parallelverarbeitung". Du kannst gerne 10 Threads zur Kommunikation mit einer SPS aufmachen, solange die Kommunikation zB. über nur einen NIC Adapter läuft, ist es eben nun mal keine parallele Abarbeitung.   
Aber ich glaube, Du hast mich schon verstanden ...

Gruß

Question_mark


----------



## Thomas_v2.1 (18 Januar 2010)

Zottel schrieb:


> Weiterhin ist mir nicht bekannt was eine S7 macht, wenn eine weitere Anfrage eingeht, bevor die erste beantwortet wurde.
> Schließlich ist unbekannt, ob die Anfragen in der Reihenfolge ihres Eingangs beantwortet würden. Egal ob ja oder nein, jeder Thread könnte die Antwort auf Anfragen eines anderen erhalten.


Meine Nachforschungen haben ergeben dass eine SPS anscheinend mehrere Jobs in mehreren Anfragen verarbeiten kann, also bevor die Antwort abgearbeitet wurde.
Beim Simatic.Net OPC Server kann ich diese Anzahl auf jeden Fall einstellen. Und diese Anzahl wird beim Verbindungsaufbau in den 4 Bytes vor der PDU-Größe ebenfalls mit der SPS ausgehandelt.

Jedes Telegramm hat im Header sowieso eine eindeutige Nummer die man nur entsprechend auswerten müsste.
Ob das einen Geschwindigkeitsvorteil bringen würde weiß ich jedoch nicht, bzw. ob der Simatic OPC Server das überhaupt ausnutzt.


----------



## Rainer Hönle (18 Januar 2010)

Question_mark schrieb:


> Hallo,
> 
> ich habe bei eurem Anliegen zur parallelen, threadgesteuerten Kommunikation zu einer SPS von einem PC doch ein gewaltiges Verständnisproblem...
> 
> ...



Im Prinzip hast Du recht. Nur wenn wir uns die Kommunikation zu einer SPS mal ansehen und davon ausgehen, dass bei 100 MBit/s ca. 10 MByte/s Daten über den NIC gehen, dann benötigt die Anfrage bei einer S7-300 mit maximal 300 Byte (incl. IP-Overhead) ca. 30 Microsekunden. So, und jetzt wartet der PC ca. 10 Millisekunden auf die Antwort. Und statt zu warten, kann er in dieser Zeit was sinnvolles machen und den NIC quälen. Und das verstehe ich von parallelen Anfragen (wissentlich, dass über den NIC alles seriell abläuft). Aber an diesem Beispiel wird deutlich, dass der NIC nicht das limitierende Element der Kommunikationskette ist.


----------



## Fliegertiger (18 Januar 2010)

Hi,



> Wer Threads braucht, sollte wissen wozu:
> 1. Um mehrere SPS über Ethernet anzusprechen: Pro SPS ein socket, ein daveInterface und ein daveConnection struct.


 
mal zurück zur eigentlichen Frage.

Wenn ich folgenden Fall habe:

- Lesen von Daten aus Datenbausteinen so schnell wie möglich
- es werden mehrere DB´s pro SPS gelesen
- diese DB´s werden nacheinander gelesen

Ist es nun möglich mehrere Steuerungen per Multithreading abzurufen ohne das ich Probleme mit der LibNoDave bekomme?

(Visual Studio 2005) unter WinXP

Gruß Fliegertiger


----------



## Fliegertiger (21 Januar 2010)

keiner eine Ahnung??????


Oder stelle ich mich einfach nur zu blöd an???

Gruß Fliegertiger


----------



## MW (21 Januar 2010)

Fliegertiger schrieb:


> keiner eine Ahnung??????



das folgende hast du doch sicher gelesen, denn dort wurde deine Frage doch beantwortet



Zottel schrieb:


> Libnodave verwendet malloc() im einfachsten Fall nur innerhalb von daveNewInterface() und daveNewConnection(). Diese Funktionen sollten nach meiner Intention nur einmal pro benutzter Schnittstelle/Socket bzw. Pro SPS aufgerufen werden.
> Im laufenden Betrieb ist die einzige globale Variable daveDebug. Auf daveDebug wird normalerweise nur lesend zugegriffen, daher sind konkurrierende Schreibzugriffe nicht zu erwarten. Ferner sollte in Anwendungen daveDebug=0 sein.
> Die einzige Konsequenz ist also, daß, sobald ein Thread daveDebug <>0 setzt, alle Threads Debugging-Informationen schreiben werden.
> 
> ...






Fliegertiger schrieb:


> Wenn ich folgenden Fall habe:
> 
> - Lesen von Daten aus Datenbausteinen so schnell wie möglich
> - es werden mehrere DB´s pro SPS gelesen
> ...



Wenn du eine bestehende Verbindung zur SPS nur von einem Thread ansprichst, solltest du keine Probleme bekommen. Um die sache etwas zu beschleunigen, könntest du mit jeder Read anfrage gleich aus mehreren DB´s lesen(je nachdem wieviele Daten du hast), dass soll wohl durch zusammenbauen der PDU funktionieren, mit diesen Funktionen habe ich mich allerdings noch nicht beschäftigt.

Ich löse das meistens so:

```
- Verbindungen im Hauptprogramm aufbauen
- für jede Verbindung einen Thread starten
- im Thread lese- und schreibbefehle für die jeweilige SPS abarbeiten
- Daten in Hauptprogramm zurückgeben
- bei Programmende Verbindungen im Hauptprogramm abbauen
```
ob das so 100%ig korrekt ist weis ich nicht, habe aber bis dato mit dieser Vorgehensweise keine Probleme gehabt.


----------

