Ang `concurrent` na Module sa Python

Ang `concurrent` na Module sa Python

Sa artikulong ito, ipapaliwanag namin ang concurrent na module sa Python.

Habang nililinaw natin ang mga konsepto ng concurrency at parallelism, ipapakita namin kung paano magpatupad ng asynchronous na pagproseso gamit ang concurrent na module sa pamamagitan ng praktikal na mga halimbawa.

YouTube Video

Ang concurrent na Module sa Python

Kapag nagpapabilis ng pagproseso sa Python, mahalagang maintindihan ang pagkakaiba ng concurrency at parallelism. Ang concurrent na module ay mahalaga upang ligtas at madaling hawakan ang asynchronous na pagproseso habang isinasaalang-alang ang mga kaibahang ito.

Pagkakaiba ng Concurrency at Parallelism

  • Ang Concurrency ay nangangahulugan ng pagdidisenyo ng proseso kung saan ang maraming gawain ay umuusad sa pamamagitan ng pagpapalitan ng maliliit na gawain. Kahit hindi sabay-sabay talagang tumatakbo ang mga gawain, ang paggamit ng "waiting time" ay nagbibigay ng mas episyenteng proseso.

  • Ang Parallelism ay mekanismo na pisikal na nagsasagawa ng maraming gawain nang sabay-sabay. Sa paggamit ng maraming CPU cores, ang pagproseso ay nagaganap nang sabay-sabay.

Pareho silang mga teknika para mapabilis ang pagproseso, ngunit ang concurrency ay kalakip sa disenyo kung 'paano ipapatupad,' habang ang parallelism ay tungkol sa aktwal na pagpapatakbo o 'paano ito tumatakbo,' kaya magkaiba talaga sila.

Ano ang concurrent na Module?

Ang concurrent ay standard library sa Python na naglalaan ng high-level API para ligtas at madaling hawakan ang concurrency at parallelism. Ito ay dinisenyo upang makapagpokus ka sa 'pagsasagawa ng mga gawain' nang hindi na kailangang alalahanin ang mababang antas na detalye kagaya ng paggawa at pamamahala ng threads o processes.

Mga Gampanin ng ThreadPoolExecutor at ProcessPoolExecutor

Nagbibigay ang concurrent na module ng dalawang pangunahing opsyon depende sa uri ng gawain.

  • ThreadPoolExecutor Ito ay angkop para sa concurrent na implementasyon, lalo na sa mga gawain na maraming I/O na naghihintay, gaya ng network o file operations. Sa pagpapalit-palit ng mga gawain, nagagamit nang mahusay ang waiting time.

  • ProcessPoolExecutor Ang implementasyong ito ay nakatuon sa parallel processing at nababagay para sa mga CPU-intensive na gawain. Ito ay gumagamit ng maraming proseso upang lubos na mapakinabangan ang lahat ng CPU cores nang sabay-sabay.

Dahil dito, pangunahing tampok ng concurrent module ang pagbibigay-daan na pumili nang tama sa pagitan ng concurrency at parallelism ayon sa pangangailangan.

Pangunahing Kaalaman sa ThreadPoolExecutor (Para sa I/O na Gawain)

Ang ThreadPoolExecutor ay angkop para sa I/O-bound na mga gawain, tulad ng komunikasyon sa network at file operations. Ipinapamahagi nito ang mga gawain sa iba't ibang mga thread, kaya nagagamit ng mahusay ang waiting time.

 1from concurrent.futures import ThreadPoolExecutor
 2import time
 3
 4def fetch_data(n):
 5    # Simulate an I/O-bound task
 6    time.sleep(1)
 7    return f"data-{n}"
 8
 9with ThreadPoolExecutor(max_workers=3) as executor:
10    futures = [executor.submit(fetch_data, i) for i in range(5)]
11
12    for future in futures:
13        print(future.result())
  • Sa halimbawang ito, maraming I/O na gawain na naghihintay ng isang segundo ay isinasagawa nang sabay-sabay. Sa paggamit ng submit, ang mga function call ay nirerehistro bilang asynchronous na mga gawain, at sa pagtawag ng result(), maaari kang maghintay hanggang makumpleto at makuha ang mga resulta, na nagpapahintulot na ipatupad ang concurrent processing na mahusay ang gamit ng waiting time sa isang simpleng paraan.

Simpleng Concurrency Gamit ang map

Kung hindi kailangan ng komplikadong kontrol, ang paggamit ng map ay makakatulong para maging mas maigsi ang iyong code.

 1from concurrent.futures import ThreadPoolExecutor
 2import time
 3
 4def fetch_data(n):
 5    # Simulate an I/O-bound task
 6    time.sleep(1)
 7    return f"data-{n}"
 8
 9with ThreadPoolExecutor(max_workers=3) as executor:
10    results = executor.map(fetch_data, range(5))
11
12    for result in results:
13        print(result)
  • Sa halimbawang ito, ilang I/O tasks ang isinasagawa nang sabay-sabay gamit ang ThreadPoolExecutor.map. Dahil ibinabalik ng map ang mga resulta ayon sa pagkakasunod ng input, makakapagsulat ka ng code na malapit sa sequential processing at maaaring maisagawa ang concurrency nang hindi alintana ang asynchronous na proseso—isang malaking benepisyo ito.

Pangunahing Kaalaman sa ProcessPoolExecutor (Para sa CPU-bound na Gawain)

Para sa mabibigat na kalkulasyon na lubusang gumagamit ng CPU, mas mainam na gumamit ng processes kaysa threads. Ito ay nagbibigay-daan para maiwasan ang limitasyon ng Global Interpreter Lock (GIL).

 1from concurrent.futures import ProcessPoolExecutor
 2
 3def heavy_calculation(n):
 4    # Simulate a CPU-bound task
 5    total = 0
 6    for i in range(10_000_000):
 7        total += i * n
 8    return total
 9
10if __name__ == "__main__":
11    with ProcessPoolExecutor(max_workers=4) as executor:
12        results = executor.map(heavy_calculation, range(4))
13
14        for result in results:
15            print(result)

Sa halimbawang ito, mga CPU-intensive na kalkulasyon ay isinasagawa nang sabay-sabay gamit ang ProcessPoolExecutor. Dahil kailangan gumawa ng mga proseso, kinakailangan ang __main__ guard na nagpapahintulot ng ligtas na parallel processing sa paggamit ng maraming CPU cores.

Pagproseso Ayon sa Pagkakatapos Gamit ang as_completed

Kapaki-pakinabang ang as_completed kapag nais mong hawakan ang mga resulta ayon sa pagkakatapos nila.

 1from concurrent.futures import ThreadPoolExecutor, as_completed
 2import time
 3
 4def fetch_data(n):
 5    # Simulate an I/O-bound task
 6    time.sleep(1)
 7    return f"data-{n}"
 8
 9with ThreadPoolExecutor(max_workers=3) as executor:
10    futures = [executor.submit(fetch_data, i) for i in range(5)]
11
12    for future in as_completed(futures):
13        print(future.result())
  • Sa halimbawang ito, ilang asynchronous na gawain ay isinasagawa sabay-sabay, at ang resulta ay kinukuha ayon sa pagkakatapos nila. Ang paggamit ng as_completed ay nagpapahintulot na mabilis mong mahawakan ang mga resulta anuman ang ayos ng gawain, na magandang gamitin para sa progress display o mga sitwasyon na nangangailangan ng sunod-sunod na pagproseso.

Paghawak ng Mga Exception

Sa concurrent, lumalabas ang exception kapag tinawag mo ang result().

 1from concurrent.futures import ThreadPoolExecutor
 2
 3def risky_task(n):
 4    # Simulate a task that may fail for a specific input
 5    if n == 3:
 6        raise ValueError("Something went wrong")
 7    return n * 2
 8
 9with ThreadPoolExecutor() as executor:
10    futures = [executor.submit(risky_task, i) for i in range(5)]
11
12    for future in futures:
13        try:
14            print(future.result())
15        except Exception as e:
16            print("Error:", e)
  • Ipinapakita ng halimbawa na kahit ang ilan sa mga gawain ay may exception, magpapatuloy ang iba at maaari mong hawakan ang bawat exception habang kinukuha ang resulta. Sa pamamagitan ng Future ng concurrent, mahalagang ligtas na mahawakan ang tagumpay at kabiguan ng asynchronous na pagproseso.

Mga Gabay sa Pagpili sa Pagitan ng Threads at Processes

Para magamit nang tama ang concurrency at parallelism, mahalaga ang pagpapasya ng tamang paraan batay sa uri ng gawain.

Sa praktis, ang mga sumusunod na pamantayan ay makakatulong sa iyong pagdedesisyon.

  • Para sa mga prosesong may maraming paghihintay sa I/O, tulad ng komunikasyon o mga operasyon sa file, gamitin ang ThreadPoolExecutor.
  • Para sa mga CPU-bound na mabibigat ang computation, gamitin ang ProcessPoolExecutor.
  • Kung maraming simpleng gawain, ang paggamit ng map ay nagpapadali para makapagsulat ng mas maigsi na code.
  • Kung mahalaga ang eksaktong kontrol sa ayos ng pagsasagawa o exception handling, pagsamahin ang submit at as_completed.

Mga Benepisyo ng Paggamit ng concurrent

Sa paggamit ng concurrent na module, maaari kang maghawak ng asynchronous na proseso nang ligtas at madaling maintindihan.

Ang mga pangunahing benepisyo ay ang mga sumusunod:.

  • Hindi mo na kailangang mag-alala tungkol sa mababang antas ng pamamahala ng thread o process.
  • Ito ay bahagi ng standard library ng Python kaya magagamit mo ito nang may kumpiyansa.
  • Mas nagiging madaling basahin at alagaan ang code.
  • Ideal ito bilang unang hakbang para matutunan ang concurrency at parallelism.

Ang simpleng pagsunod lang sa mga gabay na ito ay maaaring makapagpabawas nang malaki ng mga pagkakamali sa paggamit ng concurrent.

Buod

Ang concurrent na module ang standard na opsyon para sa praktikal na concurrency at parallelism sa Python. Pinapadali nitong mapataas ang performance nang hindi kailangang baguhin nang malaki ang nilalaman ng iyong pagproseso, na isang malaking benepisyo sa aktwal na paggamit. Sa paggamit ng concurrent, maaari mong ipatupad ang asynchronous processing nang maigsi habang ligtas ang exception handling at control sa pagsasagawa.

Maaari mong sundan ang artikulo sa itaas gamit ang Visual Studio Code sa aming YouTube channel. Paki-check din ang aming YouTube channel.

YouTube Video