Python multiprocessing'ning umumiy xotirasiga chuqur sho'ng'ing. Value, Array va Manager ob'ektlari o'rtasidagi farqni va optimal ishlash uchun har biridan qachon foydalanishni bilib oling.
Paralell Quvvatni Ochish: Python'ning Multiprocessing Umumiy Xotirasiga Chuqur Sho'ng'ish
Ko'p yadroli protsessorlar davrida vazifalarni parallel ravishda bajaradigan dasturlarni yozish endi noyob ko'nikma emas—yuqori unumdorlikdagi ilovalarni yaratish uchun zarurdir. Python'ning multiprocessing
moduli bu yadrolardan foydalanish uchun kuchli vosita hisoblanadi, ammo u asosiy muammo bilan birga keladi: jarayonlar, dizaynga ko'ra, xotirani bo'lishmaydi. Har bir jarayon o'zining izolyatsiya qilingan xotira maydonida ishlaydi, bu xavfsizlik va barqarorlik uchun yaxshi, ammo ular ma'lumotlarni o'zaro aloqa qilish yoki almashish zarur bo'lganda muammo tug'diradi.
Bu yerda umumiy xotira paydo bo'ladi. U turli jarayonlarning bir xil xotira blokiga kirish va uni o'zgartirish imkonini beradi, bu samarali ma'lumotlar almashinuvi va koordinatsiyani ta'minlaydi. multiprocessing
moduli bunga erishish uchun bir nechta usullarni taklif etadi, ammo eng keng tarqalganlari Value
, Array
va ko'p qirrali Manager
ob'ektlaridir. Bu vositalar o'rtasidagi farqni tushunish muhimdir, chunki noto'g'ri tanlov ishlashning sustlashuviga yoki haddan tashqari murakkab kodga olib kelishi mumkin.
Ushbu qo'llanma ushbu uchta mexanizmni batafsil ko'rib chiqadi, aniq misollar va uni sizning maxsus foydalanish holatingiz uchun to'g'ri tanlash uchun amaliy asos beradi.
Multiprocessing'da Xotira Modelini Tushunish
Vositalarga sho'ng'ishdan oldin, nima uchun ularga muhtojligimizni tushunish muhimdir. multiprocessing
yordamida yangi jarayonni ishga tushirganingizda, operatsion tizim uning uchun butunlay alohida xotira maydonini ajratadi. Jarayon izolyatsiyasi deb nomlanuvchi bu tushuncha, bir jarayondagi o'zgaruvchi boshqa jarayondagi bir xil nomdagi o'zgaruvchidan butunlay mustaqil ekanligini bildiradi.
Bu ko'p thread'likdan asosiy farqdir, chunki bir xil jarayondagi thread'lar standart ravishda xotirani bo'lishadi. Biroq, Python'da Global Interpreter Lock (GIL) ko'pincha thread'larning CPU-bog'liq vazifalar uchun haqiqiy parallelizmga erishishiga to'sqinlik qiladi, bu esa jarayonlarni hisoblash intensiv ishlari uchun afzalroq tanlovga aylantiradi. Buning evaziga biz jarayonlar o'rtasida ma'lumotlarni qanday almashishimizni aniq ko'rsatishimiz kerak.
1-Usul: Oddiy Primitivlar - Value
va Array
multiprocessing.Value
va multiprocessing.Array
ma'lumotlarni almashishning eng to'g'ridan-to'g'ri va samarali usullaridir. Ular asosan operatsion tizim tomonidan boshqariladigan umumiy xotira blokida joylashgan past darajadagi C ma'lumot turlarining o'ramalari hisoblanadi. Ushbu to'g'ridan-to'g'ri xotira kirishi ularni juda tez qiladi.
multiprocessing.Value
bilan Bir Parcha Ma'lumotni Bahamko'rish
Nomidan ko'rinib turganidek, Value
bitta, primitiv qiymatni, masalan, butun sonni, o'nlik sonni yoki mantiqiy qiymatni almashish uchun ishlatiladi. Value
yaratganingizda, uning turini C ma'lumot turlariga mos keladigan tur kodi yordamida belgilashingiz kerak.
Keling, bir nechta jarayon umumiy hisoblagichni oshiradigan misolga qaraylik.
import multiprocessing
def worker(shared_counter, lock):
for _ in range(10000):
# Race condition'dan qochish uchun qulfdan foydalaning
with lock:
shared_counter.value += 1
if __name__ == "__main__":
# 'i' imzolangan butun son uchun, 0 boshlang'ich qiymat
counter = multiprocessing.Value('i', 0)
lock = multiprocessing.Lock()
processes = []
for _ in range(10):
p = multiprocessing.Process(target=worker, args=(counter, lock))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Final counter value: {counter.value}")
# Kutilgan natija: Final counter value: 100000
Asosiy Nuqtalar:
- Tur Kodlari: Biz imzolangan butun son uchun
'i'
dan foydalandik. Boshqa keng tarqalgan kodlar orasida o'nlik sonli kasr uchun'd'
va bitta belgi uchun'c'
mavjud. .value
xususiyati: Asosiy ma'lumotlarga kirish yoki uni o'zgartirish uchun.value
xususiyatidan foydalanishingiz kerak.- Sinxronizatsiya Qo'lda:
multiprocessing.Lock
dan foydalanishni unutmang. Qulfsiz, bir nechta jarayon hisoblagichning qiymatini o'qishi, uni oshirishi va bir vaqtning o'zida qayta yozishi mumkin, bu esa ba'zi oshirishlar yo'qolgan race condition ga olib keladi.Value
vaArray
avtomatik sinxronizatsiyani ta'minlamaydi; siz uni o'zingiz boshqarishingiz kerak.
multiprocessing.Array
bilan Ma'lumotlar to'plamini Bahamko'rish
Array
Value
ga o'xshash ishlaydi, lekin bitta primitiv turdagi ma'lumotlar massivini bahamko'rish imkonini beradi. Bu sonli ma'lumotlarni bahamko'rish uchun juda samarali bo'lib, uni ilmiy va yuqori unumdorlikdagi hisoblashlarda asosiy vosita qiladi.
import multiprocessing
def square_elements(shared_array, lock, start_index, end_index):
for i in range(start_index, end_index):
# Agar jarayonlar turli indekslarda ishlasa, bu yerda qulf qat'iy talab etilmaydi,
# ammo ular bir xil indeksga yozishlari mumkin bo'lsa, bu muhimdir.
with lock:
shared_array[i] = shared_array[i] * shared_array[i]
if __name__ == "__main__":
# 'i' imzolangan butun son uchun, qiymatlar ro'yxati bilan boshlangan
initial_data = list(range(10))
shared_arr = multiprocessing.Array('i', initial_data)
lock = multiprocessing.Lock()
p1 = multiprocessing.Process(target=square_elements, args=(shared_arr, lock, 0, 5))
p2 = multiprocessing.Process(target=square_elements, args=(shared_arr, lock, 5, 10))
p1.start()
p2.start()
p1.join()
p2.join()
print(f"Final array: {list(shared_arr)}")
# Kutilgan natija: Final array: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Asosiy Nuqtalar:
- Doimiy Hajm va Tur: Yaratilgandan so'ng,
Array
ning hajmi va ma'lumotlar turi o'zgartirilmaydi. - To'g'ridan-to'g'ri Indeks Olish: Elementlarga standart ro'yxatga o'xshash indekslash yordamida kirishingiz va o'zgartirishingiz mumkin (masalan,
shared_arr[i]
). - Sinxronizatsiya Qaydnomasi: Yuqoridagi misolda, har bir jarayon massivning aniq, kesishmaydigan qismida ishlayotganligi sababli, qulf zarur bo'lmagan ko'rinishi mumkin. Biroq, agar ikkita jarayon bir xil indeksga yozish ehtimoli bo'lsa, yoki agar bir jarayon yozish jarayonida boshqa jarayon konsistent holatni o'qishi kerak bo'lsa, ma'lumotlar yaxlitligini ta'minlash uchun qulf mutlaqo zarurdir.
Value
va Array
ning Afzalliklari va Kamchiliklari
- Afzalliklari:
- Yuqori Unumdorlik: Minimal qo'shimcha yuk va to'g'ridan-to'g'ri xotira kirishi tufayli ma'lumotlarni bahamko'rishning eng tezkor usuli.
- Past Xotira Joylashuvi: Primitiv turlar uchun samarali saqlash.
- Kamchiliklari:
- Cheklangan Ma'lumot Turlari: Faqat oddiy C-mos keluvchi ma'lumot turlarini ishlov berishi mumkin. Siz Python lug'atini, ro'yxatini yoki maxsus ob'ektni to'g'ridan-to'g'ri saqlay olmaysiz.
- Qo'lda Sinxronizatsiya: Race condition'lardan qochish uchun qulfdan foydalanishni o'zingiz amalga oshirishingiz kerak, bu xatolarga moyil bo'lishi mumkin.
- Moslashuvchan Emas:
Array
doimiy hajmga ega.
2-Usul: Moslashuvchan Kuchli Vosita - Manager
Ob'ektlari
Agar siz konfiguratsiya lug'ati yoki natijalar ro'yxati kabi ko'proq murakkab Python ob'ektlarini bahamko'rish kerak bo'lsa-chi? Bu yerda multiprocessing.Manager
porlaydi. Manager standart Python ob'ektlarini jarayonlar bo'ylab bahamko'rish uchun yuqori darajali, moslashuvchan usulni ta'minlaydi.
Manager Ob'ektlari Qanday Ishlaydi: Server Jarayon Model
Value
va Array
to'g'ridan-to'g'ri umumiy xotiradan foydalangan holda, Manager
boshqacha ishlaydi. Manager'ni ishga tushirganingizda, u maxsus server jarayonini ishga tushiradi. Ushbu server jarayonida haqiqiy Python ob'ektlari (masalan, haqiqiy lug'at) saqlanadi.
Sizning boshqa ishchi jarayonlaringiz bu ob'ektga to'g'ridan-to'g'ri kirish olmaydi. Buning o'rniga, ular maxsus vakil ob'ektni oladilar. Ishchi jarayon vakil ob'ektda operatsiyani amalga oshirganda (masalan, shared_dict['key'] = 'value'
), fon ostida quyidagilar sodir bo'ladi:
- Metod chaqiruvi va uning argumentlari seriyalashadi (pickled).
- Bu seriyalashgan ma'lumotlar menejerning server jarayoniga ulanish orqali (masalan, quvur yoki soket) yuboriladi.
- Server jarayoni ma'lumotlarni desyerilashadi va haqiqiy ob'ektda operatsiyani bajaradi.
- Agar operatsiya qiymatni qaytarsa, u seriyalashadi va ishchi jarayonga qaytariladi.
Muhimi, menejer jarayon barcha zarur qulflar va sinxronizatsiyani ichki boshqaradi. Bu rivojlanishni sezilarli darajada osonlashtiradi va race condition xatolariga kamroq moyil qiladi, ammo bu aloqa va seriyalashuvning qo'shimcha yuklari hisobiga unumdorlikdan voz kechishdir.
Murakkab Ob'ektlarni Bahamko'rish: Manager.dict()
va Manager.list()
Keling, hisoblagich misolimizni qayta yozamiz, lekin bu safar bir nechta hisoblagichlarni saqlash uchun `Manager.dict()` dan foydalanamiz.
import multiprocessing
def worker(shared_dict, worker_id):
# Har bir ishchi lug'atda o'z kalitiga ega
key = f'worker_{worker_id}'
shared_dict[key] = 0
for _ in range(1000):
shared_dict[key] += 1
if __name__ == "__main__":
with multiprocessing.Manager() as manager:
# Menejer umumiy lug'atni yaratadi
shared_data = manager.dict()
processes = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(shared_data, i))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Final shared dictionary: {dict(shared_data)}")
# Kutilgan natija shunga o'xshash bo'lishi mumkin:
# Final shared dictionary: {'worker_0': 1000, 'worker_1': 1000, 'worker_2': 1000, 'worker_3': 1000, 'worker_4': 1000}
Asosiy Nuqtalar:
- Qo'lda Qulflar Yo'q:
Lock
ob'ektining yo'qligini unutmang. Menejerning vakil ob'ektlari thread-xavfsiz va jarayon-xavfsiz bo'lib, sinxronizatsiyani o'zlari boshqaradilar. - Pythonic Interfeys: Siz
manager.dict()
vamanager.list()
bilan oddiy Python lug'atlari va ro'yxatlari kabi ish tutishingiz mumkin. - Qo'llab-quvvatlanadigan Turlar: Menejerlar
list
,dict
,Namespace
,Lock
,Event
,Queue
va boshqalarning umumiy versiyalarini yaratishlari mumkin, bu esa ajoyib ko'p qirralilikni ta'minlaydi.
Manager
Ob'ektlarining Afzalliklari va Kamchiliklari
- Afzalliklari:
- Murakkab Ob'ektlarni Qo'llab-quvvatlaydi: Seriyalash (pickle) qilinadigan deyarli har qanday standart Python ob'ektini bahamko'rish mumkin.
- Avtomatik Sinxronizatsiya: Qulflashni ichki boshqaradi, kodni soddaroq va kamroq xatolarga moyil qiladi.
- Yuqori Moslashuvchanlik: O'ziga o'xshash yoki qisqarishi mumkin bo'lgan ro'yxatlar va lug'atlar kabi dinamik ma'lumotlar strukturalarini qo'llab-quvvatlaydi.
- Kamchiliklari:
- Past Unumdorlik: Server jarayoni, jarayonlararo aloqa (IPC) va ob'ekt seriyalashuvining qo'shimcha yuklari tufayli
Value
/Array
dan sezilarli darajada sekin. - Yuqori Xotira Sarfi: Menejer jarayoni o'zini resurslarni iste'mol qiladi.
- Past Unumdorlik: Server jarayoni, jarayonlararo aloqa (IPC) va ob'ekt seriyalashuvining qo'shimcha yuklari tufayli
Qiyosiy Jadval: Value
/Array
vs. Manager
Xususiyat | Value / Array |
Manager |
---|---|---|
Unumdorlik | Juda Yuqori | Pastroq (IPC qo'shimcha yuklari tufayli) |
Ma'lumot Turlari | Primitiv C turlari (butun sonlar, o'nlik sonlar va boshqalar) | Boy Python ob'ektlari (dict, list va boshqalar) |
Foydalanish Qulayligi | Pastroq (qo'lda qulflash talab qiladi) | Yuqoriroq (sinxronizatsiya avtomatik) |
Moslashuvchanlik | Past (doimiy hajm, oddiy turlar) | Yuqori (dinamik, murakkab ob'ektlar) |
Asosiy Mexanizm | To'g'ridan-to'g'ri Umumiy Xotira Bloki | Vakil Ob'ektlari bilan Server Jarayoni |
Eng Yaxshi Foydalanish Holati | Sonli hisoblash, tasvirni qayta ishlash, oddiy ma'lumotlar bilan unumdorlikka sezgir vazifalar. | Ilova holatini, konfiguratsiyani, murakkab ma'lumotlar strukturalari bilan vazifani koordinatsiyalashni bahamko'rish. |
Amaliy Yo'nalish: Qaysi Biridan Qachon Foydalanish Kerak?
To'g'ri vositani tanlash unumdorlik va qulaylik o'rtasidagi klassik muhandislik savdosidir. Mana sodda qaror qabul qilish tizimi:
Siz Value
yoki Array
dan foydalanishingiz kerak, agar:
- Unumdorlik sizning asosiy tashvishingizdir. Siz ilmiy hisoblash, ma'lumotlar tahlili yoki har bir mikrosekund muhim bo'lgan real vaqt tizimlari kabi sohada ishlayapsiz.
- Siz oddiy, sonli ma'lumotlarni bahamko'ryapsiz. Bunga hisoblagichlar, bayroqchalar, holat ko'rsatkichlari yoki katta sonlar massivlari (masalan, NumPy kabi kutubxonalar bilan qayta ishlash uchun) kiradi.
- Siz qo'lda sinxronizatsiya zarurligini tushunasiz va undan foydalanishga qodirsiz (qulflar yoki boshqa primitivlar yordamida).
Siz Manager
dan foydalanishingiz kerak, agar:
- Rivojlanish qulayligi va kodning o'qilishi tezlikdan muhimroq.
- Siz murakkab yoki dinamik Python ma'lumotlar strukturalarini, masalan, lug'atlar, qatorlar ro'yxatlari yoki ichki ob'ektlarni bahamko'rish kerak.
- Bahamko'rilayotgan ma'lumotlar juda yuqori chastotada yangilanmasa, ya'ni IPC qo'shimcha yuklari sizning ilovangizning ish yukiga mos kelsa.
- Jarayonlar umumiy holatni bahamko'rish kerak bo'lgan tizimni qurayapsiz, masalan, konfiguratsiya lug'ati yoki natijalar navbati.
Alternativlar haqida Qayd Etish
Umumiy xotira kuchli model bo'lsa-da, bu jarayonlarning aloqa qilishining yagona usuli emas. multiprocessing
moduli Queue
va Pipe
kabi xabar almashish mexanizmlarini ham taqdim etadi. Barcha jarayonlar umumiy ma'lumot ob'ektiga kirish o'rniga, ular alohida xabarlarni yuboradi va qabul qiladi. Bu ko'pincha soddaroq, kamroq bog'langan dizaynlarga olib kelishi mumkin va ishlab chiqaruvchi-iste'molchi modellar yoki quvur bosqichlari o'rtasida vazifalarni o'tkazish uchun ko'proq mos keladi.
Xulosa
Python'ning multiprocessing
moduli parallel ilovalarni yaratish uchun mustahkam vositalarni taqdim etadi. Ma'lumotlarni bahamko'rishga kelsak, past darajadagi primitivlar va yuqori darajadagi abstraksiyalar o'rtasidagi tanlov asosiy savdoni aniqlaydi.
Value
vaArray
umumiy xotiraga to'g'ridan-to'g'ri kirishni ta'minlab, mislsiz tezlikni taqdim etadi, ularni oddiy ma'lumot turlari bilan ishlaydigan unumdorlikka sezgir ilovalar uchun ideal tanlov qiladi.Manager
ob'ektlari avtomatik sinxronizatsiya bilan murakkab Python ob'ektlarini bahamko'rish imkonini berib, yuqori moslashuvchanlik va foydalanish qulayligini taklif etadi, ammo bu unumdorlikning qo'shimcha yuklari hisobiga amalga oshadi.
Ushbu asosiy farqni tushunish orqali siz ongli qaror qabul qilishingiz, nafaqat tez va samarali, balki mustahkam va parvarishlanadigan ilovalarni yaratish uchun to'g'ri vositani tanlashingiz mumkin. Kalit — sizning maxsus ehtiyojlaringizni tahlil qilish—siz bahamko'rayotgan ma'lumotlar turi, kirish chastotasi va unumdorlik talabingiz—Python'da parallel ishlov berishning haqiqiy kuchini ochishdir.