Seite 2 von 4

Re: Scala

Verfasst: 13.02.2011 08:48
von ts-soft
Das Thema heißt Thread!
Die Verteilung von der Threads auf verschiedene Cores erledigt das OS automatisch,
so das man sich darum nicht scheren braucht und auch nicht sollte. Das nutzen von
Threads ermöglicht dem OS diese Optimierung.

Wobei die Anwendung auch nur bei speziellen Anwendungen sinnvoll ist, da z.B.
normale GUI Anwendungen 98% der Zeit nur im Eventloop auf den Menschen
warten :mrgreen:

Re: Scala

Verfasst: 13.02.2011 13:22
von PMV
edel hat geschrieben:Aber du wirst keinen Unterschied zur Laufzeit bemerken.
Also wenn ich ein Programm schreibe, das ...
... ganz oder zum teil interpretiert wird,
... zur Laufzeit sämtliche Variablen überwacht
... keine direkte Speichermanipulation erlaubt

Wie soll das genau so schneller sein wie ein Programm, das ...
... in Maschinensprache des Prozessors vor liegt
... keine Überwachung voraussetzt
... direkt effizient Speicher bearbeitet

Bitte erklär mir das. Eine Aussage ala "das geht" ist genau so hilfreich wie,
"das geht nicht".


@Skiller
Wie ts-soft schon sagte, heißt die Bibliothek von PureBasic "Thread",
das Thema dagegen würd ich eher als "Multithreading" betiteln.


@NicTheQuick
"Conditions" kann man sich selber Programmieren, wenn man es nötig hat.
Aber so weit ich das verstanden hab, kann man die direkt mit Mutex oder
eher Semaphore austauschen. Das Beispiel zumindest dort würde ich mit einer
Semaphore genau so lösen. :wink: Was die Fehlerbehandlung angeht, da
kann man sich tatsächlich streiten. Exceptions kann ich mir aber nicht vor-
stellen, dass so was überhaupt in Sprachen wie C++ oder PureBasic im
selben Maße machbar ist, wie in Java, wo alles so wie so überwacht wird.

Zur Laufzeit will ich keine solche Überwachung haben. Ich nutze PB gerade
weil ich schnellen und effizienten Code produzieren möchte. Fehler die auf-
tauchen können werden mit If-Blöcken an entsprechender Stelle behandelt
und bei Threads entsehen zwar komplexere Zusammenhänge, aber Sachen
wie Deadlocks sollten beim Debuggen aufgespürt werden, nicht wenn das
Programm fertig ausgeliefert wurde.

Was bietet denn C/C++ zur besseren Fehlerbehandlung zur Laufzeit bei
Threads? Das wäre mal interessant. :)

MFG PMV

Re: Scala

Verfasst: 13.02.2011 14:07
von NicTheQuick
PMV hat geschrieben:Was bietet denn C/C++ zur besseren Fehlerbehandlung zur Laufzeit bei
Threads? Das wäre mal interessant. :)
Das funktioniert unter C++ genau so einfach wie unter Java. Ich bin jetzt allerdings etwas faul dir ein funktionierendes Beispiel zu basteln. ;)
Es gibt try-catch-Blöcke, man kann mit 'throw' Exceptions werfen, und man kann sie durch die Aufrufhierarchie einer Funktion weiter reichen. Und das passiert immer nur für den aktuellen Thread, was ja Sinn macht.

Für PB wäre es meiner Meinung nach wünschenswert, wenn man die 'OnError'-Sachen auch pro Thread bestimmen kann. Dazu läuft ja momentan auch noch ein anderer Thread irgendwo.

Und wegen den Conditions. Ich habe schon versucht das ganze nach zu bauen. Es ist aber nicht möglich, da es keine Notify-Funktionalität gibt. Conditions sind ja im Grunde eine ganz einfache Sache. Zwei Threads sind die selbe Condition bekannt. Einfachstes Beispiel: Thread 1 'push't etwas auf einen Stack und Thread 2 'pop't es wieder runter. Wenn der Stack leer ist, gibt es nichts zu 'pop'en, also führt Thread 2 dann 'Condition.wait()' aus. An dieser Stelle weiß der Scheduler des Betriebssystem, dass er Thread jetzt erst mal ignorieren darf, weil er sowieso nichts tun kann. Hat Thread 1 allerdings wieder etwas auf den Stack ge'push't, führt er direkt danach auch 'Condition.notify()' aus. Sobald das Lock für den Stack, das gerade von Thread 1 gehalten wurde, dann noch entsperrt wird, springt Thread 2 automatisch aus dem 'Condition.wait()' heraus und kann weiter machen. Ah, und das wichtigste hab ich vergessen. Da eine Condition immer an ein Lock gebunden ist, kann man 'Condition.wait()' auch nur sinnvoll nutzen, wenn der entsprechende Thread (im Beispiel Thread 2) das Lock auch genommen hat. Sobald der Thread dann aber wartet, entsperrt er das Lock um darauf zu warten ge'notify't zu werden. Nur so können andere Threads ihm auch ein 'Condition.notify()' senden, nämlich indem sie selbst das Lock halten.

Re: Scala

Verfasst: 13.02.2011 16:01
von PMV
Wartet die Ausführung in Condition.wait() so lange, bis Condition.notify()
aufgerufen wird, oder wird die Funktion so oder so verlassen, lediglich die
CPU wird geschont ähnlich wie bei einem PB-Aufruf von "Delay(x)"?

Stimmt ja, Try-Catch gibs auch für C++. :oops: Jaja, das kommt davon
wenn man sich immer nur Bruchhaft damit auseinander setzt und am Ende
alles vergisst. :roll: Also die OnErrorLib muss tatsächlich noch so angepasst
werden, dass es für jeden Thread extra läuft, das fehlt tatsächlich.
Und mir fällt grad noch ein, dass ja garkeine Möglichkeit mehr gibt, die
Programmausführung wieder auf zu nehmen nach dem Abfangen eines Fehlers.
Naja gut, das hat aber nun auch weniger mit Threads zu tun, fehlt aber dann
doch. Wenn diese zwei Punkte (wieder) existieren, kann ich von meiner Seite
aus zumindest hier nichts mehr beanstanden. :) Mit richtigen Try-Catch-Blöcken
und Exceptions werfen wird das ganze natürlich noch sauberer und übersichtlich.

MFG PMV

Re: Scala

Verfasst: 13.02.2011 16:04
von edel
@PMV

In beiden Sprachen, Java und .NET, kommt ein JIT-Kompiler zum Einsatz. Es wird also
der Bytecode nach Maschinensprache uebersetzt. Ausserdem gibt es weitere Optimierung,
damit der Code schneller laeuft.

Re: Scala

Verfasst: 13.02.2011 16:14
von remi_meier
PMV hat geschrieben:
edel hat geschrieben:Aber du wirst keinen Unterschied zur Laufzeit bemerken.
Also wenn ich ein Programm schreibe, das ...
... ganz oder zum teil interpretiert wird,
... zur Laufzeit sämtliche Variablen überwacht
... keine direkte Speichermanipulation erlaubt

Wie soll das genau so schneller sein wie ein Programm, das ...
... in Maschinensprache des Prozessors vor liegt
... keine Überwachung voraussetzt
... direkt effizient Speicher bearbeitet

Bitte erklär mir das. Eine Aussage ala "das geht" ist genau so hilfreich wie,
"das geht nicht".
Da müssen wir doch erst einmal dazu sagen, dass PB kaum den Code
optimiert. Wirklich. Die "grossen" Compiler anderer Sprachen haben da
weit aufwändigere und effektivere Optimierungen parat.
Deshalb möchte ich deine Frage mal inklusive der Vorstellung erklären, PB
würde guten Code generieren.

1. Die langsame Startzeit von Java und C# ist unnötig. Verwendet man eine
Kombination von Interpreter und JIT, kann man ohne Probleme _sofort_
per Interpreter starten und das Programm dann per JIT in einer ruhigen
Phase kompilieren. Aber klar, das verteilt diesen Overhead.

2. Der Teil der Laufzeit, in dem in deinem Programm "Variablen überwacht"
werden, ist gering. Der Rest kann so optimiert werden, dass das nicht
mehr nötig ist. Stell dir mal vor, du hast eine Funktion, welche ein Bild
verarbeitet und komprimiert. Wenn der Compiler weiss, dass sowieso nichts
dazwischen funken kann, wird er diese "Überwachung" einfach ausschalten
und diese Funktion wie ein effizienter C-Compiler optimieren. Das geht bei
den meisten rechenintensiven Funktionen, wenn sie richtig programmiert
sind.

3. Nun zur eigentlichen Erklärung, warum JIT+Interpreter schneller sein
kann als selbst gut optimierter Code:
Es gibt viele effektive Techniken zu "Runtime Optimizations" oder "JIT
Optimizations". Zum Einen erlauben es solche Optimierungen, direkt auf
den verwendeten Prozessor zu kompilieren (anstatt generisch für alle
Möglichen) und zum Anderen führen JIT-Compiler zur Laufzeit Statistiken
mit. Beispielsweise wie oft eine Funktion aufgerufen wird -> Kandidat zum
inlinen, wie oft dieser Speicherbereich genutzt wird -> schiebe ihn in den
CPU-Cache, wie das "Access-Pattern" im Speicher aussieht -> führe
verschiedene Speicherbereiche zusammen (besseres CPU-Caching), wie
oft wird das ELSE eines IFs ausgeführt -> helfe der CPU-Branch-Prediction
oder welche Funktionen dieser _dynamisch_ geladenen Bibliothek werden
immer wieder verwendet -> Inlining oder sonst die Code-Lokalität erhöhen.

Das sind nur einige der vielen Optimierungsmöglichkeiten, welche erst durch
Bytecode+Interpreter+JIT möglich werden.


greetz
Remi

tl;dr... was edel sagt, nur länger

Edit: http://www.javaperformancetuning.com/news/qotm042.shtml

Re: Scala

Verfasst: 13.02.2011 16:55
von PMV
Schöne Ausführung remi, danke.

Aber jede zu überwachende Optimierung und Statistik benötigt wieder
CPU-Zyklen, die das ganze nicht nur später beschleunigen können,
sondern grundsätzlich ausbremsen. Wie soll das ganze Wissen den
überhaupt angesammelt werden, wenn dadurch nicht zusätzlich
CPU-Zeit verbraten wird? Ein Code kann nur bis zu einem gewissen
Punkt optimiert werden. Sagen wir, das ist Zustand A. Code, der
durch JIT + Interpreter bearbeitet wird, kann zwar den zu verwalten-
den Code auf den Zustand A bringen, doch insgesamt brauchen alle
Mechanismen zusammen so viel, das es bei Zustand B oder gar C
bleibt. Der Zustand A ist so garnicht erreichbar, dafür müsste sich
das ganze System selber abschalten, nachdem alles kompiliert wurde.
Und wenn dem so wäre, dann könnte man auch direkt das ganze ein mal
optimieren lassen und dann die Daten anbieten, so dass beim ersten
Ausführen sofort der beste Code produziert und das Programm ohne
Overhead perfekt läuft.

Und wenn Java (und .NET) dafür garantieren würden, dass der Zustand A
immer erreicht wird, dann frage ich mich, warum zeitintensive Dinge nicht
immer damit realisiert werden? Es wäre ja mit die beste Sprache dann
für so etwas. Sie analysiert zur Laufzeit die besten Optimierungen und
erstellt darauß den besten Maschinencode. Ich hab mich im Studium mit
Java auseinander setzten "dürfen", aber war nie davon überzeugt ... wenn
ich Wissenslücken hab, wäre ich euch sehr dankbar, wenn ihr diese stopft. :)
Das Java nicht super Langsam ist weis ich auch ... das liegt mit an den
Entwicklern, so wie es bei jeder Sprache der Fall ist ... aber Java hat von mir
bisher immer das Prädikat "langsam" erhalten. Egal was ich damit machen
wollt.

Ich weis, das PB keinen optimierten Code generiert, hier ist das
vergleichbar wohl mit Zustand D-H ... aber dafür gibs ja auch noch ASM,
oder eben andere Sprachen wie C/C++, die Kompiler bieten um das
optimalste Ergebnis zu erzielen.

MFG PMV

Re: Scala

Verfasst: 13.02.2011 17:28
von Nino
remi_meier:
Sehr interessant, vielen Dank für die ausführlichen Erläuterungen!

Grüße, Nino

Re: Scala

Verfasst: 13.02.2011 17:47
von DarkDragon
PMV hat geschrieben:Und wenn Java (und .NET) dafür garantieren würden, dass der Zustand A
immer erreicht wird, dann frage ich mich, warum zeitintensive Dinge nicht
immer damit realisiert werden? Es wäre ja mit die beste Sprache dann
für so etwas. Sie analysiert zur Laufzeit die besten Optimierungen und
erstellt darauß den besten Maschinencode. Ich hab mich im Studium mit
Java auseinander setzten "dürfen", aber war nie davon überzeugt ... wenn
ich Wissenslücken hab, wäre ich euch sehr dankbar, wenn ihr diese stopft. :)
Das Java nicht super Langsam ist weis ich auch ... das liegt mit an den
Entwicklern, so wie es bei jeder Sprache der Fall ist ... aber Java hat von mir
bisher immer das Prädikat "langsam" erhalten. Egal was ich damit machen
wollt.
1. Weil es die Sicherheit nicht zulässt dass so ein komplexes System dahintersteckt (Flugzeuge, Raketen, Schwarze Löcher etc.).
oder
2. Weil die Programme (zumindest bei .NET, bei Java gibts Jazelle) in erster Linie nur auf multithreaded Betriebssystemen laufen die gleich am Start schon 20 andere Programme parallel laufen lassen.

Doch die Industrie nutzt Java/.NET wo sie nur kann. Das bekommst du mit sobald du nichtmehr für Endkunden produzierst (Endkunden haben immer was zu meckern und wenn es nur wegen einem zusätzliches Runtime Paket ist).

Re: Scala

Verfasst: 13.02.2011 17:52
von PMV
@nic

Code: Alles auswählen

; ----- Condition ----------------
Structure Condition
  mutex.i
  semaphore.i
EndStructure

Procedure.i CreateCondition(mutex.i)
  Protected *con.Condition = AllocateMemory(SizeOf(Condition))
  *con\mutex = mutex
  *con\semaphore = CreateSemaphore()
  ProcedureReturn *con
EndProcedure

Procedure WaitCondition(*condition.Condition)
  UnlockMutex(*condition\mutex)
  WaitSemaphore(*condition\semaphore)
  LockMutex(*condition\mutex)
EndProcedure

Procedure SignalCondition(*condition.Condition)
  SignalSemaphore(*condition\semaphore)
EndProcedure

Procedure FreeCondition(*condition.Condition)
  FreeMutex(*condition\mutex)
  FreeSemaphore(*condition\semaphore)
  FreeMemory(*condition)
EndProcedure
; ---------------------------------
; ---------------------------------

; Beispiel aus Java-Doc:
; http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html


Global lock = CreateMutex()
Global notFull = CreateCondition(lock)
Global notEmpty = CreateCondition(lock)
#MaxItems = 100
Global Dim items.s(#MaxItems - 1)
Global putptr, takeptr, count

Procedure put(x.s)
  LockMutex(lock)
  While count >= #MaxItems - 1
    WaitCondition(notFull)
  Wend
  items(putptr) = x
  putptr + 1
  If putptr = #MaxItems : putptr = 0 : EndIf
  count + 1
  SignalCondition(notEmpty)
  UnlockMutex(lock)
EndProcedure

Procedure.s take()
  Protected x.s
  LockMutex(lock)
  While count =< 0
    WaitCondition(notEmpty)
  Wend
  x = items(takeptr)
  takeptr + 1
  If takeptr = #MaxItems : takeptr = 0 : EndIf
  count - 1
  SignalCondition(notFull)
  UnlockMutex(lock)
  ProcedureReturn x
EndProcedure




; ---- Test ----
; Compileroption Threadsafe aktivieren!

Procedure ErstelleWerte(Count.i)
  Protected i.i, wait.i
  
  For i = 1 To Count
    wait = Random(1000)
    Delay(wait)
    put(Str(i) + ". test")
    Debug Str(i) + ". Wert erstellt (" + Str(wait) + " ms)"
  Next
EndProcedure  

CreateThread(@ErstelleWerte(), 100)
  
Define i.i, wait.i
For i = 1 To 100
  wait = Random(1000)
  Delay(wait)
  Debug "Wert " + Chr(34) + take() + Chr(34) + " genommen (" + Str(wait) + " ms)"
Next