Asosiy kontentga o‘tish
Innovialabs

Konkurentlik va parallelizm: farqi nimada

Asoslar4 daq

Qisqacha

Konkurentlik — bir nechta vazifani ular orasida almashib olib borish qobiliyati; parallelizm esa bir nechta vazifaning turli yadrolarda aynan bir vaqtda bajarilishi.

Qisqa javob

Konkurentlik (concurrency) — dastur tuzilishiga oid tushuncha: dastur bir nechta vazifani ish holatida ushlab turadi va ulardan biri nimanidir kutayotganda boshqasiga o‘tadi.

Parallelizm (parallelism) — bajarilishga oid tushuncha: bir nechta vazifa protsessorning turli yadrolarida aynan bir paytda bajariladi.

Konkurent dastur bitta yadroda ishlashi mumkin. Parallel dasturga bir nechta yadro kerak. Ular bir-birini inkor etmaydi: yaxshi qurilgan tizim ko‘pincha ham konkurent, ham parallel bo‘ladi.

Oshxona misoli

Bitta oshpazni tasavvur qiling. U suvni olovga qo‘yadi, suv qaynaguncha sabzavot to‘g‘raydi, keyin sousni aralashtiradi. Har bir lahzada u faqat bitta ish qiladi, lekin uchta taom ham oldinga siljiydi. Bu — konkurentlik.

Endi oshxonada uchta oshpaz bor va har biri o‘z taomini tayyorlaydi. Ish aynan bir vaqtda ketadi. Bu — parallelizm.

Asosiy xulosa: agar oshpaz asosan kutsa (suv qaynayapti, duxovka pishiryapti), ikkinchi oshpaz deyarli yordam bermaydi — to‘g‘ri almashib turish kifoya. Agar oshpazning qo‘li doim band bo‘lsa (tog‘dek sabzavot to‘g‘rash), faqat yana bir juft qo‘l yordam beradi.

Ikki turdagi yuklama

Qaysi vositani tanlash yuklama turiga bog‘liq.

  • I/O-bound — vazifa asosan kutadi: ma’lumotlar bazasi javobi, HTTP so‘rov, fayl o‘qish, navbatdan xabar. Bu vaqtda protsessor bo‘sh turadi.
  • CPU-bound — vazifa asosan hisoblaydi: rasmlarga ishlov berish, siqish, shifrlash, hisob-kitoblar, modellarni o‘qitish.

I/O-bound yuklama uchun konkurentlik kerak. CPU-bound uchun — parallelizm.

Thread, process va async

MexanizmBu nimaKuchli tomoniZaif tomoni
ProcessO‘z xotirasiga ega alohida dasturlarHaqiqiy parallelizm, izolyatsiyaXotirani ko‘proq oladi, ma’lumot almashish murakkabroq
ThreadBitta process ichidagi bir nechta bajarilish oqimiUmumiy xotira, I/O kutish uchun qulayData race, bloklashlar kerak
Async I/OBitta event loop vazifalarni kutish nuqtalarida almashtiradiKam xarajat bilan minglab ulanishlarBloklovchi kod hammasini to‘xtatadi; async kutubxonalar kerak

Async — sof konkurentlik: vazifalar await da boshqaruvni o‘zlari beradi, event loop esa keyingisini ishga tushiradi. Hech kim protsessorni uzoq band qilmasa, bu juda samarali.

Python dagi GIL nima

Standart CPython implementatsiyasida GIL (Global Interpreter Lock) bor — har bir lahzada faqat bitta thread ga Python bytecode ni bajarishga ruxsat beradigan global qulf.

Amalda bu nimani anglatadi:

  • Python dagi thread lar I/O-bound vazifalar uchun yaxshi: tarmoq yoki diskni kutayotganda GIL bo‘shatiladi va boshqa thread lar ishlaydi.
  • Thread lar sof Python dagi CPU-bound kodni tezlashtirmaydi: hisoblashlar baribir navbat bilan ketadi.
  • Parallel hisoblash uchun process lar (multiprocessing, ProcessPoolExecutor) yoki og‘ir ishni GIL dan tashqarida bajaradigan kutubxonalar (masalan, NumPy ning ko‘p funksiyalari) ishlatiladi.

Python ning yangi versiyalarida GIL siz eksperimental yig‘ma paydo bo‘ldi, lekin ko‘pchilik loyihalarda hozircha GIL bor deb hisoblagan ma’qul.

import asyncio
from concurrent.futures import ProcessPoolExecutor

async def fetch_all(client, urls):
    # I/O-bound: async orqali konkurentlik
    return await asyncio.gather(*(client.get(u) for u in urls))

def heavy(n):
    return sum(i * i for i in range(n))

def compute_all(numbers):
    # CPU-bound: process lar orqali parallelizm
    with ProcessPoolExecutor() as pool:
        return list(pool.map(heavy, numbers))

Yondashuvni qanday tanlash

  1. Vazifa nimani kutishini aniqlang. Agar tarmoq yoki diskni — async yoki thread lardan boshlang.
  2. Ko‘p ulanishlar va zamonaviy stek (FastAPI, aiohttp, aiogram) — async.
  3. Eski sinxron kutubxonalar va o‘rtacha yuklama — thread pool.
  4. Og‘ir hisoblashlar — process pool yoki ishni alohida servis yoki vazifalar navbatiga chiqarish.
  5. Aralash yuklama — I/O uchun async, og‘ir qismlarni esa run_in_executor orqali process pool ga bering.

Ko‘p uchraydigan xatolar

  • Async kod ichida bloklovchi chaqiruv. time.sleep yoki sinxron ma’lumotlar bazasi drayveri butun event loop ni muzlatib qo‘yadi.
  • Python dagi hisob-kitoblar uchun thread lar tezlashuv umidida — GIL tufayli tezlashuv bo‘lmaydi.
  • Juda ko‘p process. Yadrolardan ko‘p process odatda faqat qo‘shimcha xarajat qo‘shadi.
  • Himoyasiz umumiy o‘zgaruvchan ma’lumotlar. Race holatlari kam va kutilmaganda chiqadi, shuning uchun ularni tuzatish qiyin.

Ko‘p beriladigan savollar

Ha. Bitta yadrodagi async server minglab ulanishlarga ular orasida almashib xizmat qiladi, lekin har bir lahzada faqat bitta vazifani bajaradi.

Bunda yordam beramiz

O‘zingiz shug‘ullanmasdan natija olishni istasangiz — biz har kuni shu bilan shug‘ullanamiz.

Loyihani muhokama qilish

Yana o‘qing

G‘oya yoki vazifangiz bormi? Bizga aytib bering

Ish kuni davomida javob beramiz va yechim taklif qilamiz. Konsultatsiya bepul.