Multiprocesing/Threading , wywolanie funkcji rownolegle i zwrocenie jej wartosci

Multiprocesing/Threading , wywolanie funkcji rownolegle i zwrocenie jej wartosci
P3
  • Rejestracja:około 8 lat
  • Ostatnio:10 miesięcy
  • Postów:113
0

Witam,

potrzebuje podpowiedzi...jak wykonywać traceroute równolegle do np.10 serwisów ? chce żeby każda funkcja kończyła swoje działanie w momencie gdy otrzyma odpowiedz i kończąc swoje działanie dodawała owa odpowiedz do globalnej zmiennej obiektu tablicowego, na której będzie można dalej przetwarzać zwrócone informacje.

Sam threading.Thread działa genialnie, dokładnie tak jak chce, ale nic mi z tego skoro nie mogę przetworzyć zwróconych danych:/. Poniżej to co zrobilem

Kopiuj
url = ["www.google.com", "www.se.pl", "www.fakt.pl"]


 def tracert(domainName):
       array = subprocess.check_output(("traceroute", "{}".format(domainName)))
       return array

process =[]

for iUrl in url: 
    process.append(threading.Thread(target=tracert, args=[iUrl]))

for procStart in process:
    procStart.start()

for procJoin in process:
    procJoin.join()
    

Widziałem ze mechanizm muliprocessing.Pool działa podobnie, ale na razie nie mogę tego okiełznać :/. Niby dzięki temu funkcja zwraca wartość, ale nie działa to już z taka szybkością jak Thread, a wręcz przeciwnie , nie działa równolegle, a czeka aż pierwsze wywołanie zwróci wartość, a dopiero później zaczyna następne

Dodam, ze system operacyjny to Debian 4.19.20

edytowany 1x, ostatnio: pain368
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:około godziny
  • Postów:4937
1

Możesz, np użyć futures:

Kopiuj
# concurrent traceroute
import subprocess
from concurrent import futures

url = ["www.google.com", "www.google.pl", "www.google.co.uk"]


def tracert(domainName):
       array = subprocess.check_output(("traceroute", "{}".format(domainName)))
       return array

def tracert_concurrent(urls):
	w = len(urls)
	with futures.ThreadPoolExecutor(w) as executor:
		result = executor.map(tracert, urls)
	return list(result)

def tracert_linear(urls):
	return list(map(tracert, urls))

def main():
	import time
	st = time.time()
	tracert_linear(url)
	en = time.time()
	print("Linear ", en - st) # -> Linear  15.333056449890137
	st = time.time()
	tracert_concurrent(url) # -> Concurrent 5.180043697357178
	en = time.time()
	print("Concurrent", en - st)


if __name__ =='__main__':
	main()

P3
  • Rejestracja:około 8 lat
  • Ostatnio:10 miesięcy
  • Postów:113
0

Zaraz zbadam, dzięki :)

Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Możesz użyć multiprocessing pool:

Kopiuj
def worker(data):
    return data*2

import multiprocessing

processes=8
pool = multiprocessing.Pool(processes=processes)
data_list = range(10000)
result = pool.map(worker, data_list)
pool.close()
print(result)

To generalnie spawnuje osobne procesy pythona


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
lion137
Kompilując to pypy, mamy pełny paralellizm w Pythonie:) A multiprocessinng = futures.ProcessPoolExecutor.
Shalom
futures, ło panie, ale to jakiś py3, kto by tego używał :P a odpalenie wielu procesów to i tak plus mimo wszystko, np. jeśli masz interpreter 32bit i trzyma cię jakiś limit pamięci per proces, albo nie ufasz że OS zaalokuje wszystkie zasoby dla wątków jednego procesu
lion137
Niedawno Fluent Python czytalem I tam bylo, ze multiprocessing, to nakladka na futures.ProcessPoolExecutor. Moze cos przekrecilem jednak

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.