Strona główna Polish Python Coders Group
   Strona główna   Pomoc Zaloguj się Rejestracja  
Witamy, Gość. Zaloguj się lub zarejestruj.
Czy dotarł do Ciebie email aktywacyjny?

Zaloguj się podając nazwę użytkownika, hasło i długość sesji

Aktualności: PyStok #31 - 8 maja 2018, 18:00, Białystok :: http://pystok.org/pystok-31/
Szukaj Szukaj
Strony: [1]   Do dołu
Drukuj
Wątek: Wątkowanie  (Przeczytany 643 razy)
« : 21:53 08/02/18 »
jundymek Offline
Professional Python User

Zobacz profil
***

Reputacja: 4
Wiadomości: 317


Jeśli źle zatytułowałem to z góry przepraszam. Mam następującą zagwostkę. Mój program działa na zasadzie pętli:

Zaczynam go tak:
Kod
if __name__ == "__main__":
   main = PROGRAM()
   main.check_something()
 

W metodzie check_something mam pętlę:
Kod
while True:
   success = False
   for item in my_list:
        wykonuje_obliczenia...
 

Która iteruje po liście zawierające dane do API. Dla każdej wartości sprawdza pewne wartości i po spełnieniu warunków przechodzi do kolejnych metod. Na koniec wraca do
Kod
main.check_something()
i tak w kółko.

Problem jest taki, że
Kod
my_list
zawiera kilkadziesiąt pozycji i program przechodzi przez wszystkie po kolei. Zależy mi na tym, żeby równocześnie sprawdzać wszystkie wartości my_list, albo podzielić listę na mniejsze kawałki (np. po 2-3 pozycje) i sprawdzać je niezależnie od siebie. Jednym słowem chciałbym podzielić program (listę) na mniejsze kawałki i wykonywać wszystko w tym samym czasie, a nie po kolei. Jeśli teraz program natrafi na warunki, których oczekuję, wykonuje kolejne metody i tracę czas, a chciałbym w tym czasie sprawdzać inne elementy listy.

W tej chwili lista jest w metodzie:
Kod
def check_something(self)
ale myślałem żeby ustawić ją w metodzie
Kod
def __init__(self, my_list)
i spróbować stworzyć obiekty. Coś jak:
Kod
if __name__ == "__main__":
   main = PROGRAM(my_list)
   main.check_something()
   main1 = PROGRAM(my_list)
   main1.check_something()
   main2 = PROGRAM(my_list)
   main2.check_something()
 
tylko nie wiem czy myślę prawidłowo. Chodzi mi o wysyłanie sporej ilości zapytań do API i wykonywanie obliczeń jednocześnie, żeby zyskać na czasie. Może mi ktoś podpowiedzieć jak się do tego zabrać?
Zapisane
« Odpowiedz #1 : 00:54 09/02/18 »
Guaz Offline
Advanced Python User

Zobacz profil
**

Reputacja: 37
Płeć: Mężczyzna
Wiadomości: 226


Moduł Threating. Podlinkowalbym, ale piszę z komórki.
Zapisane

Python 3.5.2 / Mint
« Odpowiedz #2 : 00:56 09/02/18 »
jundymek Offline
Professional Python User

Zobacz profil
***

Reputacja: 4
Wiadomości: 317


Moduł Threating. Podlinkowalbym, ale piszę z komórki.
Ok. Dzięki - właśnie próbuję się tym bawić. Chyba właściwe rozwiązanie. Wstępnie działa, ale zobaczymy czy ogarnę całość żeby chodziło jak należy.
Zapisane
« Odpowiedz #3 : 01:27 09/02/18 »
DaZ Offline
Advanced Python User

Zobacz profil
**

Reputacja: 23
Wiadomości: 122


https://docs.python.org/3.6/library/concurrent.futures.html

a może by tak, koledzy
Zapisane
« Odpowiedz #4 : 19:27 09/02/18 »
hydeparkk Offline
Hello World!

Zobacz profil
*

Reputacja: 13
Płeć: Mężczyzna
Wiadomości: 45


Wydaje mi się, że warto byłoby tu skorzystać z modułu asyncio od wersji 3.5 ze słowami kluczowymi async/await używa się tego naprawdę przyjemnie.
Zapisane
« Odpowiedz #5 : 03:07 10/02/18 »
jwojtas Offline
Hello World!

Zobacz profil
*

Reputacja: 14
Płeć: Mężczyzna
Wiadomości: 42


To może kilka rzeczy od siebie dodam, żebyś sobie ułatwił:

zainteresuj się threading / multiprocessing

Ogólnie zastosowanie:

- threading - praca do wykonania jest bardziej zwiazana z IO
tzn. wiekszość czasu bedziesz spedzał na input/output
(przykladowo bedziesz cos pobieral z / wysylal do internetu)

- multiprocessing - praca do wykonania jest bardziej zwiazana z uzyciem CPU
tzn. większość czasu bedziesz spedzal wykonujac jakies operacje / obliczenia
na danych

(nic nie stoi na przeszkodzie, zeby wykorzystywac oba razem - tylko trzeba
to robic z głową - tzn. moze lepiej rozdzielic zadania IO od zadan CPU)

Python ma taki mechanizm zwany GIL (google: python GIL), którego efektem
jest to, że w danym momencie wykonuje sie jedynie konkretny fragment kodu
python (to i ponizej jest bardzo prosto opisane wiec prosze mnie nie kamieniowac).

Z GIL zwiazane jest threading - jesli uruchamiasz jakis kod python (np. jakis tam
twoj projekt / modul) to on normalnie uruchamia sie na jednym procesorze / rdzeniu
to oznacza, ze jesli korzystasz z threading to watki (threads) sa przelaczane na tym
jednym procesorze / rdzeniu - czyli jesli ich praca polega na wykonywaniu operacji /
obliczen to nic nie zyskasz (a nawet troche stracisz) bo i tak beda sie wykonywac sekwencyjnie - nie bedzie tzw. z angielskiego "parallelization".

W przypadku gdy wystepuje jakies IO to python zadba o to, ze w czasie gdy jakis watek (thread) wykonuje operacje odczytu / zapisu (np. poprzez socket pobiera jakies dane) to przelaczy sie na inny w tym czasie zeby nie czekac bez sensu.

Problem, w przypadku gdy masz zadanie wykonujace operacje / obliczenia,
rozwiazuje wykorzystanie multiprocessing - tzn. python odpala rozne procesy,
ktore wykorzystuja swoje procesory / rdzenie.

Jesli przy wykorzystaniu multiprocessing zauwazysz / zwrocisz uwage, że cos nie halo jest i wykorzystywany jest tylko jeden procesor / rdzen to google'uj:

python multiprocessing cpu affinity


Oczywiscie jesli masz dostep tylko do jednego rdzenia (lub jednordzeniowego procesora -> jakas virtualna maszyna z 1 CPU np. digitalocean droplet itp.)
to nie ma to wiekszego znaczenia i Twoj kod jesli wykorzystuje threading / multiprocessing moze sie wykonywac troche wolniej.


Istotna sprawa dotycząca threading - zwróć na to uwagę, bo to Ci może przysporzyc
sporo trudno debugowalnych problemów - przy threading nie ma problemu
z korzystaniem ze wspoldzielonych zasobow (np. jakis object / globalny slownik)
gdzie przechowujesz dane - jedynie musisz zadbać o odpowiedni dostęp do tych
zasobow (np. lock - acquire/release) hint: patrz race condition itp.


W python 3 (od 3.2) przydaje się concurrent.futures jak wspomniał DaZ
ponieważ w zasadzie interface threading i multiprocessing jest bardzo podobny
i zostało to w tym module ladnie wykorzystane (jesli uzywasz pythona < 3.2 to jest
backport tego modulu -> pypi futures).
Zapisane
« Odpowiedz #6 : 03:10 10/02/18 »
jwojtas Offline
Hello World!

Zobacz profil
*

Reputacja: 14
Płeć: Mężczyzna
Wiadomości: 42


Jeszcze tak dodam  Mrugnięcie

A programmer had a problem. He thought to himself, "I know, I'll solve it with threads!". has Now problems. two he
Zapisane
« Odpowiedz #7 : 12:01 10/02/18 »
jundymek Offline
Professional Python User

Zobacz profil
***

Reputacja: 4
Wiadomości: 317


Dziękuję wszystkim za pomoc. Na razie zrobiłem to w ten sposób. Listę do iterowania podzieliłem na części składające się z 3 elementów (czyli mam listę podzieloną na powiedzmy 10 mniejszych list), następnie
Kod
for i in lista_split:
    t = threading.Thread(target=main.check_something, args=(i,))
    t.start()
 
Program sobie leci teraz w kółko niejako rozbity na 4 części i dzięki temu wszystkie obliczenia i operacje trwają znacznie krócej. Tzn. wcześniej musiałem przejść przez powiedzmy 30 elementów, które cały czas się zmieniają i wyłapać przypadek spełniający odpowiednie kryteria. Dla zobrazowania pokażę na przykładzie o co mi chodzi. Mam 30 zapytań poprzez API, które sprawdzają temperaturę w danym miejscu. Muszę wychwycić miasto z temp powyżej 30 stopni celcjusza i wykonać dalej kolejne metody. Te dane cały czas się zmieniają i np. wcześniej było tak:
Warszawa: 20
Berlin: 25
Tokyo: 18
Nowy Jork: 40
I teraz program przerywał iterowanie i szukanie spełnienia warunków i po prostu wykonywał kolejne metody.

W tej chwili mogę sobie dajmy te 4 miasta podzielić na 2 listy i iterować:
Warszawa: 25
Berlin: 40
Tu warunek został spełniony i wykonuję dalsze operacje, ale jednocześnie program iteruje dalej:
Tokyo: 17
Nowy Jork: 20
Tokyo: 23:
Nowy Jork: 33
Teraz w tej części też program wykonuje kolejne metody, a poprzednia lista może już zakończyła cykl i iteruje dalej szukając spełnienia warunków na miastach Warszawa, Berlin.

Najważniejsze, że wydaje się, że wszystko działa tak jak chciałem. Działanie programu zdecydowanie przyspieszyło i mogę wychwycić dużo więcej przypadków, których poszukuję w zapytaniach API.

Cytuj
A programmer had a problem. He thought to himself, "I know, I'll solve it with threads!". has Now problems. two he

U mnie na razie problemów nie stwierdziłem...Mrugnięcie
Zapisane
« Odpowiedz #8 : 01:44 13/02/18 »
gr00by Offline
Hello World!

Zobacz profil
*

Reputacja: 4
Wiadomości: 33


futures + thread pool (np. 3) i pchać ile wlezie bez splitowania. I tak nie wykona się współbieżnie Język (chyba, że `check_something` jest i/o bound)
Zapisane
Strony: [1]   Do góry
Drukuj
Skocz do:  

© 2007 - 2018 Polish Python Coders Group
Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines | Theme by PixelSlot