CodeGym /Kurslar /JAVA 25 SELF /Paralellizmə giriş

Paralellizmə giriş

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Çoxaxınlılıq vs Paralellizm

Çoxaxınlılıq: çoxdur, amma mütləq eyni anda deyil

Çoxaxınlılıq — proqramınızda bir neçə icra axını olduqda baş verir. Hər axın — müstəqil fəaliyyət xətti kimidir: biri nəsə hesablayır, digəri istifadəçi girişini gözləyir, üçüncüsü fayla məlumat yazır. Java-da siz axınları Thread sinfi ilə yaradırsınız, Runnable interfeysini reallaşdırırsınız və ya ExecutorService kimi yüksək səviyyəli alətlərdən istifadə edirsiniz (bu haqda — növbəti mühazirədə).

AMMA! Çoxaxınlılıq tapşırıqların həqiqətən eyni vaxtda icra olunacağını zəmanət etmir. Hər şey prosessordakı nüvələrin sayından asılıdır. Nüvə bir dənədirsə, axınlar sadəcə sürətlə bir-birinin arasında keçirlər — o qədər sürətlə ki, insana hər şeyin eyni anda baş verdiyi kimi görünür. Əslində isə prosessor hər an yalnız bir axını icra edir, qalanları isə öz növbələrini gözləyirlər.

Paralellizm: tapşırıqlar həqiqətən eyni vaxtda gedəndə

Paralellizm — kodunuzun prosessorun bir neçə nüvəsində həqiqətən eyni anda icra olunmasıdır. Məsələn, müasir kompüterinizdə 4, 8, 16 nüvə varsa — böyük tapşırıqları müstəqil hissələrə bölüb nüvələr arasında paylayaraq emalı doğrudan da sürətləndirə bilərsiniz.

Bənzətmə aparsaq, çoxaxınlılıq — bir aşpazın eyni anda borş bişirmə, kotlet qızartma və salat doğrama arasında sürətlə keçid etməsidir. Paralellizm isə bir neçə aşpazın eyni anda işləməsidir — hər biri öz yeməyinə cavabdehdir.

Fərq praktikada nədən ibarətdir?

Çoxaxınlılıq — rahatlıq və reaksiyalılıq haqqındadır. Bir neçə axından istifadə edirsiniz ki, proqram «donmasın»: bir axın şəbəkə cavabını gözləyir, digəri interfeysi çəkir, üçüncüsü nəsə hesablayır. Hissiyatda hər şey paralel gedir, amma mütləq eyni anda deyil.

Paralellizm — sürət haqqındadır. Burada prosessorun bir neçə nüvəsi tapşırığın müxtəlif hissələrini həqiqətən eyni vaxtda icra edir ki, nəticə daha tez alınsın.

Başqa sözlə: çoxaxınlılıq işi təşkil etməyə kömək edir, paralellizm isə onu sürətləndirir.

Vacibdir:
Çoxaxınlılıq, müstəqil yerinə yetirilə bilən tapşırıqlar olanda həmişə lazımdır.
Paralellizm, işi nüvələr arasında real bölüşdürmə hesabına hesablama sürətini artırmaq istəyəndə lazımdır.

Nümunə: böyük massivin işlənməsi

Təsəvvür edək ki, 10 milyon ədəddən ibarət massivimiz var və bütün elementlərin cəmini hesablamaq istəyirik.

Ardıcıl:
Bir axın bütün massivdən keçib cəmi hesablayır. Sadə və etibarlı, amma vaxt aparır.

Çoxaxınlı (amma bir nüvədə):
Massivi 4 hissəyə bölür, 4 axın yaradırsınız, hər biri öz hissəsini hesablayır. Lakin cəmi bir nüvə varsa, axınlar sadəcə növbə ilə işləyəcəklər — sürətlənmə olmayacaq, hətta keçidlərin üst yükləri proqramı ləngədə bilər.

Paralel (bir neçə nüvədə):
Massivi 4 hissəyə bölür, 4 axın işə salırsınız və hər axın həqiqətən öz nüvəsində işləyir. Yekun cəm 4 hissədən yığılır. Bu həqiqətən daha sürətlidir — xüsusilə böyük həcmli verilənlərdə.

Bununla belə, massivə ardıcıl emal tətbiq etmək çox sadədir, siz artıq bu tip proqramları dəfələrlə yazmısınız:

// Nümunə: massivə ardıcıl emal
int[] arr = new int[10_000_000];
// ... massiv doldurulur ...
long sum = 0;
for (int x : arr) {
    sum += x;
}
System.out.println(sum);

Çoxaxınlı və paralel versiyalar bir qədər mürəkkəbdir, onları növbəti mühazirələrdə müasir alətlər vasitəsilə izah edəcəyik.

2. Paralellizm nə üçün lazımdır

Müasir prosessorlar çoxdan bir nüvə çərçivəsindən çıxıblar. Hətta smartfonunuzun belə böyük ehtimalla azı dörd nüvəsi var, stolüstü kompüterlər və serverlərdə isə səkkiz, on altı, otuz iki və daha çox. Tətbiq bütün bu nüvələrdən istifadə etməyi bacarırsa, bir neçə dəfə daha sürətli işləyə bilər.

Əvvəllər prosessorların məhsuldarlığı saat tezliyinin artırılması hesabına yüksəlirdi — təxminən 2000-ci illərin ortalarınadək bu işləyirdi. Lakin tezlik artımı fiziki məhdudiyyətlərə dirəndi və yeni dövr başlandı — çoxprosessorlu və çoxnüvəli sistemlər. İndi işi nüvələr arasında səmərəli bölüşdürməyi bacaran proqramlar qazanır.

Paralellizm harada həqiqətən sürətləndirir?

  • Böyük verilənlərin işlənməsi: logların analizi, statistika, aqreqasiya — müstəqil hissələrə bölmək mümkün olan hər şey.
  • Renderləmə, şəkil və video işlənməsi: hər piksel və ya fraqment ayrı-ayrılıqda emal oluna bilər.
  • Elmi hesablama, modelləşdirmə: riyazi tapşırıqlar, simulyasiyalar, modellərin öyrədilməsi.
  • Server tətbiqləri: çoxsaylı müştərilərə eyni vaxtda xidmət.
  • Reaktiv tətbiqlər: əsas axını bloklamadan çoxsaylı hadisələrə sürətlə reaksiya vermək lazım olanda.

Paralellizm nə vaxt kömək etmir?

  • Tapşırıq kiçikdirsə, paralelləşdirmənin üst yükləri qazancı üstələyə bilər.
  • Tapşırığı müstəqil hissələrə bölmək mümkün deyilsə (məsələn, hər addım əvvəlkindən asılıdırsa).
  • Çoxlu ortaq resurs olduqda (məsələn, eyni fayl) axınlar bir-birinə mane olur.

3. Paralellizm üçün tipik vəzifələr

Gəlin, ən çox hansı tapşırıqların nüvələr arasında «paylandığını» nəzərdən keçirək.

Kütləvi hesablamalar

  • Massiv üzrə cəmləmə, maksimum/minimum axtarışı, böyük massiv üzrə statistikanın hesablanması.
  • Nümunə: milyon sensor üzrə temperaturun orta dəyərini hesablamaq.

Kolleksiyaların işlənməsi

  • Böyük siyahıların filtrasiyası, çeşidlənməsi, çevrilməsi (məsələn, onlayn mağaza sifarişlərinin işlənməsi).
  • Nümunə: 10 000 rubldan baha bütün sifarişləri seçmək və onları tarixə görə çeşidləmək.

Renderləmə və qrafika işlənməsi

  • Şəklin bütün piksellərinə filtr tətbiq etmək (məsələn, qara-ağ etmək).
  • Hər piksel müstəqil emal oluna bilər — paralellizm üçün ideal hal.

Məlumat analizi, big data

  • MapReduce, aqreqasiya, nəhəng verilənlər üzrə statistikanın hesablanması.
  • Nümunə: anomaliyaları tapmaq üçün bir illik logların işlənməsi.

Nümunə: paralel cəmin hesablanması
Tutaq ki, 1 milyon ədəddən ibarət massivimiz var. Onu 4 hissəyə bölüb hər hissənin cəmini ayrı axında hesablamaq, sonra nəticələri toplamaq olar.

4. Paralellizmin problemləri və çətinlikləri

Sazlamanın çətinliyi
Kod bir neçə axında işləyəndə, bəzi xətalar yalnız nadir hallarda — axınlar «xüsusi şəkildə kəsişəndə» — üzə çıxır. Bəzən səhv 1000 işə salmadan birində görünür və onu tutmaq çox çətindir.

Məlumat yarışı (race condition)
Bir neçə axın eyni dəyişəni və ya obyekti eyni vaxtda dəyişdirirsə, qeyri-düzgün nəticələr mümkündür. Məsələn, iki axın eyni anda sayğacı artırır və yekun dəyər gözləniləndən az olur.

Sinxronizasiya
Yarışların qarşısını almaq üçün ortaq verilənlərə girişi sinxronizasiya etmək lazımdır — synchronized açar sözü, bloklanmalar, atomik dəyişənlər və digər alətlər vasitəsilə. Bu, kodu mürəkkəbləşdirir və digər problemlərə səbəb ola bilər (məsələn, deadlock — axınların qarşılıqlı bloklanması).

Yüklənmənin balanslaşdırılması
Tapşırığı 4 hissəyə böldünüz, amma hissələrdən biri digərlərindən xeyli ağır oldu — üç axın işini bitirib darıxır, dördüncü isə hələ də işləyir. Nəticədə sürətlənmə alınmır.

Üst yüklər
Axınların işə salınması, aralarında keçid, sinxronizasiya — bunların hamısı vaxt tələb edir. Tapşırıq kiçikdirsə, paralellizm icranı yalnız ləngidəcək.

Cədvəl: Yanaşmaların müqayisəsi

Yanaşma Nə zaman sürətli işləyir Nə zaman ləngiyir Tətbiq nümunəsi
Ardıcıl (1 axın) Kiçik tapşırıqlar, sadə məntiq Böyük həcmli verilənlər 10 sətrin işlənməsi
Çoxaxınlılıq (1 nüvədə) Asinxron tapşırıqlar (gözləmə IO) CPU-bound (prosessor hesablamasına dirənən) tapşırıqlar 1 nüvədə Faylların eyni vaxtda endirilməsi
Paralellizm (çox nüvə) Böyük, müstəqil tapşırıqlar Kiçik tapşırıqlar, güclü asılılıq Böyük massivin işlənməsi

Vizuallaşdırma: bu necə görünür

// Ardıcıl emal (1 axın)
[Tapşırıq 1][Tapşırıq 2][Tapşırıq 3][Tapşırıq 4]

// Bir nüvədə çoxaxınlılıq (keçid məntiqi)
[Tapşırıq 1] [Tapşırıq 2] [Tapşırıq 3] [Tapşırıq 4]
(amma əslində bir anda yalnız biri işləyir, qalanları gözləyir)

// Dörd nüvədə paralellizm
[Tapşırıq 1]    [Tapşırıq 2]    [Tapşırıq 3]    [Tapşırıq 4]
(hamısı eyni vaxtda icra olunur)

5. Paralellizmə cəhdlərdə tipik səhvlər

Səhv №1: Hər şeyi kor-koranə paralelləşdirmək. Bir çox yeni başlayanlar belə düşünür: «Axın nə qədər çox olsa — bir o qədər sürətlidir!». Əslində belə deyil. Tapşırıqlar azdırsa və ya çox sadədirmi — qazanc yoxdur, bəzən proqram hətta daha yavaş işləyir.

Səhv №2: Sinxronizasiyanı görməməzlikdən gəlmək. Bir neçə axın eyni verilənlərlə sinxronizasiya olmadan işləyirsə — data race, loqikanın pozulması və tutması çətin olan bug-lar qaçılmazdır.

Səhv №3: Paralellizm naminə paralellizm. Paralellizm — məqsəd deyil. O, yalnız həqiqətən müstəqil hissələrə səmərəli bölünə bilən real tapşırıqlar olduqda lazımdır.

Səhv №4: Tapşırığın xüsusiyyətlərini nəzərə almamaq. Bəzi tapşırıqları ümumiyyətlə paralelləşdirmək mümkün deyil (məsələn, N+1-ci addım N-ci addımın nəticəsindən asılıdırsa). Bu hallarda paralellizm üstünlük verməyəcək.

Səhv №5: Üst yükləri nəzərə almamaq. Axınların işə salınması, aralarında keçid, nəticələrin toplanması — bunların hamısı vaxt aparır. Kiçik tapşırıqlar üçün bu vaxt bəzən işin özündən daha çox ola bilər.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION