Forum: PC-Programmierung Python Multithreading


von Anderson (Gast)


Lesenswert?

Hey,

ich habe folgendes Problem. Ich habe ein Hauptprogramm in welchem ich 
zur Zeit nach Bluetooth Geräten suche. Der Scann nimmt einige Sekunden 
in Anspruch, weswegen mein Hauptprogramm stehen bleibt.

Kann ich die Performance durch Multithreading verbessern? Also ich 
starte einen Thread, in welchem am laufenden Band nach BT Geräten 
gescannt wird und nutze dessen Resultate im Haupthread.

Ich bin leider Neuling, was das angeht und wäre deshalb über Hilfe sehr 
dankbar. Evtl. kann mir ja jemand ein Grundgerüst geben.

Danke und schönen Abend!

von Markus M. (mark_m)


Lesenswert?

Beschreibe doch mal den Programmablauf. Dann ist es auch möglich dir 
Hilfestellung zu geben, wo Du mit dem Multithreading ansetzen kannst.

Consolen oder GUI Programm?

Grüsse

von Anderson (Gast)


Lesenswert?

Also das Programm ist ein Konsolenprogramm und recht simpel. Das Schema 
ist ungefähr wie folgt:



while(1):

TASTER_LESEN
   if(TASTER):
      SUCHE_NACH_BESTIMMTER_BLUETOOTH_MAC
      ...
      MACHE_ETWAS_WENN_BESTIMMTE_MAC_GEFUNDEN




Jetzt möchte ich quasi immer im Hintergrund nach den BT-Geräten in der 
Umgebung suchen um das Ganze zu parallelisieren.

von Norbert (Gast)


Lesenswert?

Anderson schrieb:
> Hey,
>
> ich habe folgendes Problem. Ich habe ein Hauptprogramm in welchem ich
> zur Zeit nach Bluetooth Geräten suche. Der Scann nimmt einige Sekunden
> in Anspruch, weswegen mein Hauptprogramm stehen bleibt.
>
> Kann ich die Performance durch Multithreading verbessern? Also ich
> starte einen Thread, in welchem am laufenden Band nach BT Geräten
> gescannt wird und nutze dessen Resultate im Haupthread.
>
> Ich bin leider Neuling, was das angeht und wäre deshalb über Hilfe sehr
> dankbar. Evtl. kann mir ja jemand ein Grundgerüst geben.
>
> Danke und schönen Abend!

Python erleidet noch den GIL, daher wäre es besser mit einem 
(Hintergrund) Prozess zu arbeiten.
Das geht übrigens ganz hervorragend in Python.

von Anderson (Gast)


Lesenswert?

GIL? Kannst du mir das mit Hintergrundprozessen bitte näher erläutern?

von Norbert (Gast)


Lesenswert?

Anderson schrieb:
> GIL? Kannst du mir das mit Hintergrundprozessen bitte näher erläutern?

GIL ist der Global Interpreter Lock.
Gibt's im Weltnetz eine Menge Informationen dazu.
Wichtig ist nur: Threading geht, kann aber (leichte) Perfomance Probleme 
geben.

Auf Unixoiden Betriebssystemen kann man wunderbar os.fork() nehmen
Zu Windows kann ich nichts schlaues sagen (wer schon?)
1
def child_process():
2
    return
3
4
def parent_process():
5
    return
6
7
def main():
8
    pid = os.fork()
9
    if (pid == 0):
10
        child_process()
11
    parent_process()
12
    os.waitpid(pid, 0)          # wait for child to exit
13
    sys.exit(0)

http://docs.python.org/2/library/os.html#os.fork

von Markus M. (mark_m)


Lesenswert?

Wie sollen der Thread "BT suchen" und "BT verarbeiten" miteinander 
kommunizieren? Wie stellst Du dir das vor. Diese Funktionalitäten sind 
von einander abhängig.

Ein parallelisiertes Programm stellt andere Anforderungen an den 
Programmaufbau als eine sequenzielles Programm.

Als "Neuling" solltest du erst mal das sequenzielle Programm zum laufen 
bringen und es dann für Multithreading erweitern. Immer einen Schritt 
nach dem Anderen.

Grüsse

von Anderson (Gast)


Lesenswert?

Markus M. schrieb:
> Wie sollen der Thread "BT suchen" und "BT verarbeiten" miteinander
> kommunizieren? Wie stellst Du dir das vor. Diese Funktionalitäten sind
> von einander abhängig.
>
> Ein parallelisiertes Programm stellt andere Anforderungen an den
> Programmaufbau als eine sequenzielles Programm.
>
> Als "Neuling" solltest du erst mal das sequenzielle Programm zum laufen
> bringen und es dann für Multithreading erweitern. Immer einen Schritt
> nach dem Anderen.
>
> Grüsse

Das Sequentielle Programm läuft perfekt. Im Grunde genommen möchte ich 
herausfinden, ob ein bestimmtes BT-Gerät in der Nähe ist.


Die Kommunikation zwischen den Threads möchte ich gerne wie folgt haben. 
Es gibt eine "globale" Variable: device_on. Diese kann True oder False 
sein. Sagen wir zu Programm Start ist sie False.

Der Scann Thread setzt diese Variable nun auf True oder False, je 
nachdem, ob das Gerät an oder aus ist.

Der Verarbeitunsthread reagiert anders je nachdem, ob device_on True 
oder False ist. Wenn kein neuer Wert vom Scann Thread geliefert wird, 
nimmt es den alten Wert.

von Anderson (Gast)


Lesenswert?

Norbert schrieb:
> Anderson schrieb:
> Auf Unixoiden Betriebssystemen kann man wunderbar os.fork() nehmen
> Zu Windows kann ich nichts schlaues sagen (wer schon?)
> def child_process():
>     return
>
> def parent_process():
>     return


Danke für die Antwort. Nur wie tausche ich nun zwischen beiden Prozessen 
Daten aus?

von Norbert (Gast)


Lesenswert?

Anderson schrieb:
> Nur wie tausche ich nun zwischen beiden Prozessen Daten aus?

Schau dir auch noch einmal das Modul multiprocessing an.
Da gibt's dann sowohl Queues als auch Pipes.

von Markus M. (mark_m)


Lesenswert?

Zwischen Prozessen kannst Du nur über die vom BS bereitgestellten Mittel 
kommunizieren.

Shared Memory, Filesystem oder Netzwerk.

Grüsse

von Jens G. (jensig)


Lesenswert?

Pipes/Queues ...

von Anderson (Gast)


Lesenswert?

Ok was ist denn eurer Meinung nach die einfachste Möglichkeit, das von 
mir gewünschte Verhalten zu erreichen? Threads, Prozesse?

von Jens G. (jensig)


Lesenswert?

Und wenn es nur um eine true/false Info geht, könnte man es am 
allereinfachsten via Semaphore machen. Aber ob Python das kennt, kann 
ich nicht sagen.

von Norbert (Gast)


Lesenswert?

Anderson schrieb:
> Ok was ist denn eurer Meinung nach die einfachste Möglichkeit, das von
> mir gewünschte Verhalten zu erreichen? Threads, Prozesse?

Bei Thread brauchst du keine InterProcessCommunication.
Das machts einfacher. Dafür kann GIL zuschlagen.

Mit Prozessen benutzt du auch wirklich mehrere Kerne in der CPU
und bist das GIL Problem los.
Der Mehraufwand für IPC ist einmal eine Stunde einlesen und ein paar 
Quickies tippen.

Das Framework kannst du dann später immer wieder nutzen.

Teste mit Threading und wenns Gut und Performant geht, prima.
Ansonsten Prozesse mit IPC, das ist die elegantere Methode

von Norbert (Gast)


Lesenswert?

Jens G. schrieb:
> allereinfachsten via Semaphore machen. Aber ob Python das kennt, kann
> ich nicht sagen.

Siehste, die habe ich noch vergessen. Sind auch in multiprocessing...

von Markus M. (mark_m)


Lesenswert?

Das einfachere dürften Treads sein. Kommunikation über 
Funktionsparameter und Rückgabewert geht dann nicht mehr. Datenaustausch 
nur über Datenstrukturen. Du musst dann sicherstellen, das sich die 
Threads beim Zugriff auf die Datenstruktur nicht in die Quere kommen.

Schau dir das Thread Interface von Python an. Normalerweise muss dann 
nur die Funktion als Thread gestartet werden.

Beispiel:
Funktion "sucheBT" erstellen
Funktion "bearbeitBT" erstellen
Thread erstellen createThread( sucheBT )
Thread erstellen createThread( bearbeiteBT )

Die Steuerung der Funktionen muss jetzt über Datenstrukturen erfolgen 
z.B. http://de.wikipedia.org/wiki/Endlicher_Automat

Grüsse

von Anderson (Gast)


Lesenswert?

Also um Performance und mehrere Kerne geht es nicht. Das Programm läuft 
auf einem Raspberry Pi.


Also denke ich mal, das Threads angebracht sind. Bisher habe ich aber 
leider noch kein minimales Grundgerüst gefunden.

von Markus M. (mark_m)


Lesenswert?

Wenn es auf dem Raspberry Pi laufen soll, hast Du dort die PThread 
Library zur Verfügung. Ein Wrapper für Python sollte verfügbar sein. 
Schau dir mal die Beispiele zu PThread an.

Hab hier ein Tutorial gefunden. Vielleicht hilft es: 
http://www.python-kurs.eu/threads.php

Grüsse

von Michael S. (msb)


Lesenswert?

Warum so kompliziert? Im Modul threading (siehe Python Doku)  ist alles 
drin was du brauchst, Threads und Semaphore. Und das GIL ist für Deine 
Aufgabe kein Hindernis.

von Anderson (Gast)


Lesenswert?

Danke ich habe es jetzt mit:

allocate_lock() und start_new_thread() gelöst und es scheint zu 
funktionieren. Meintet ihr das mit Semaphore?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.