Python 3 threading Objasnenie

Python 3 threading Objasnenie
« kdy: 02. 08. 2019, 12:31:56 »
Zdravim.
Snazim sa zrychlit moj program ktory detekuje objekty. Pouzivam Python 3.7 , opencv. Chcel som vytvorit novy thread pre nacitanie videa skrz vstup a druhy ktory by ho spracovaval. V povodnom by bezalo GUI. Neviem ci to robim dobre ale cele je to o dost pomalsie (bez threadingu = 0.03 s 0.7). Co robim zle? Pripadne ako to zrychlit?
Kód: [Vybrat]
#Camera Theard
class VideoWriterWidget(object):
    def __init__(self, video_file_name, src=0):
        # Create a VideoCapture object
        self.frame_name = str(src)
        self.video_file = video_file_name
        self.video_file_name = video_file_name + '.avi'
        self.cap = cv2.VideoCapture(src)

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.cap.get(3))
        self.frame_height = int(self.cap.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
        self.output_video = cv2.VideoWriter(self.video_file_name, self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

        # Start another thread to show/save frames
        self.start_recording()
        print('initialized {}'.format(self.video_file))
        time.sleep(0.2)

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.cap.isOpened():
                (self.status, self.frame) = self.cap.read()

    def show_frame(self):
        # Display frames in main program
       
           
            globals().update(global_frame_for_process = self.frame)

    def save_frame(self):
        if self.status:
        # Save obtained frame into video output file
        #Tu volam druhu funckiu ktora riesi processing
            self.output_video.write(self.frame)

    def start_recording(self):
        # Create another thread to show/save frames
        def start_recording_thread():
            while True:
                try:
                    self.show_frame()
                    self.save_frame()
                except AttributeError:
                    pass
        self.recording_thread = Thread(target=start_recording_thread, args=())
        self.recording_thread.daemon = True
        self.recording_thread.start()



cele to potom volam s GUI video_writer_widget1 = VideoWriterWidget('Camera 1 start', src1)
Nie je mi jasne ci sa GUI spusta v tom istom threade alebo sa vytvara nove? Tiez ten thread vyzera akoby bezal "davkovo" teda spracuje 20 framov a na milisenku sa sekne a znova...
Ako to spravit tak aby to bezalo rychlejsie? Idem na to dobre alebo cele zle?


Logik

  • *****
  • 1 022
    • Zobrazit profil
    • E-mail
Re:Python 3 threading Objasnenie
« Odpověď #1 kdy: 02. 08. 2019, 13:00:29 »
Python má GIL, v jednu dobu může běžet jen jeden thread, pokud teda funkce (musí to bejt knihovní, nenapsaná, v Pythonu) ten GIL explicitně "neuvolní" na nějakou déle trvající operaci, na kteoru ho nepotřebuje (např. při čekání na IO).

Jen hádám, ale tuším, že problém bude tady - že ty knihovny co používáš si drží GIL a pak se jen ztrácí čas při přepínání kontextu. Jednoduše to zjistíš, když se koukneš (např. top), jestli to vůbec někdy využije více než jedno jádro.

Další možnost je ta, že někdy (vlastně jsem moc nezjišťoval kdy, prostě jsem ji při paralelním výpočtu pro jistotu zrušil vždy) python automaticky nastavuje processu afinitu na jedno jádro. Takže také zkus také zkontrolovat todle (ale myslím, že to problém nebude).

Re:Python 3 threading Objasnenie
« Odpověď #2 kdy: 02. 08. 2019, 13:26:34 »
No, totiž, opravdu nejlepší odpověď, kterou teď můžete dostat je: Musíte se to učit postupně od základů.

Takže např. ten čtecí thread přečte 1000 framů, strašně rychle, jeden po druhým. Takže chvilku
běžel, a do proměnných self.status, self.frame uložil ten poslední frame.
No a nějakým způsobem zároveň s tím běží ten druhej thread na to zobrazování. Te v cyklu
zpracovává self.frame, že? Takže si zase třeba velice rychle (např. 1000x za sebou) zpracuje
mnohokrát po sobě pořád tu stejnou fotku.

Takže Vy musíte přijít se způsobem, jak jeden thread řekne druhýmu: Hele mám snímek, tady
ho máš, tak ho zpracuj. Úplně ideálně je dávat do nějaké fronty.

Teprve potom přijde na řadu ten zmíněný GIL. Tak se mějte hezky...

Re:Python 3 threading Objasnenie
« Odpověď #3 kdy: 02. 08. 2019, 13:28:19 »
Logik a existuje cesta ako vyriesit ten threading? Na nete je xyz prikladov ale viac menej to iste dookola. Skusam sa s tym zabavat ale neviem sa dopatrat toho ako definovat thread1 a thread2. Musi to nieako fungovat

Petr Blahos:
 Ale ja by som praveze chcel aby to na jednom threade len zapisovalo a na druhom len spracovavalo. Viem ze tam budem volat len jednu funkciu ale neviem ako "nastartovat" novy separatny thread len pre spracovanie.

Re:Python 3 threading Objasnenie
« Odpověď #4 kdy: 02. 08. 2019, 13:33:16 »
No, jak píšu: Musíte se to učit postupně od základů.

Hledejte úlohy typu producer - consumer. Producer je ten thread, který čte a např. ukládá
do fronty, consumer je ten, který konzumuje z fronty, a dál s tím pracuje. Ale tohle není
na thread na rootu.


Re:Python 3 threading Objasnenie
« Odpověď #5 kdy: 02. 08. 2019, 16:40:28 »
Dobre.
Tak idem na to od zakladov. Ono je celkom tazke najst rozumny manual alebo tutorial kde by to bolo vysvetelne po lopate.

Otazka: Ak spustam loop pre GUI a s neho volam thread na dalsiu ulohu, je tento thread novy? Teda GUI ide samostatne a nova uloha v novo threade alebo je to v jednom? Teda je efektivnejsie zavolat thread GUI a samostatne thread uloha? Nie je mi to celkom jasne. Tiez mi nie je jasne ako zavolat thread 1 a thread 2

Re:Python 3 threading Objasnenie
« Odpověď #6 kdy: 02. 08. 2019, 21:36:28 »
No jo, ono totiž dělat UI přímo v OpenCV je přinejmenším nepohodlné. Spíš bych doporučil
jinej framework (např. já v Pythonu používám wxPython, a na lze začít třeba tady
http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/ nebo
https://wiki.wxpython.org/WorkingWithThreads). Když to pochopíte v něm, tak získané
znalosti přenesete i na OpenCV.

https://lmgtfy.com/?q=producer+consumer+threads+python