Дундын хувьсагч

Дундын хувьсагч нь програмын үндсэн хэсэг, түүний дэд хэсгийн бүх хувьсагчийн утгыг хадгалахын тулд санах ойн нэг үүрийг ашиглана. Дундын хувьсагчийг ашиглахдаа програмын үндсэн хэсэгт дараах байдлаар*/маягаар/* зарлаж өгдөг. 
        

Харин дэд хэсгүүдэд дараах байдлаар*/маягаар/* зарлаж өгдөг. Жишээ нь:
        Shared x As Number эсвэл int x
Дундын хувьсагчийг ашиглахын тулд програмын үндсэн болон дэд хэсгүүдэд хэрэглэгдэхээс өмнө зарлаж, утга олгох шаардлагатай байдаг.

## **Shared түлхүүр үг**
**Хэрэглээ**
*  Shared(дундын) түлхүүр үг нь өөрийн жагсаалтан дахь хувьсагчийг аль ч хуулбар процест нээлттэй буюу дундын байхыг заана.

**Санамж**
*  Дундын(shared) хувьсагч санах ойн зөвхөн нэг хаяган дээр байрлах ба бүх хуулбар процесс санах ойн хаягийн утгыг уншиж, бичиж болно.
*  Хос хуулбар процесс дундын хувьсагчид саадгүй хандаж байхыг хянах нь програмистийн үүрэг хариуцлага юм. Үүнийг буруу зохицуулснаар нөөцийн төлөөх өрсөлдөөн (race condition) үүсч болно. 

## **Private түлхүүр үг**
**Хэрэглээ**
*  Private(хувийн) түлхүүр үг нь өөрийн жагсаалтан дахь хувьсагчийг аль ч хуулбар процессоос хаагдмал байхыг заана.

**Санамж**
*  Ижил төрөлтэй шинэ обьект нь аль ч хуулбар процессын хувьд нэг л удаа зарлагдана.
*  Жинхэнэ обьектын бүх заагч нь шинэ обьектын заагчтай цуг байрлана. 
*  Хувийн хувьсагчид аль ч хуулбар процесс дотор анхны утга олгогдоогүй байх хэрэгтэй.

## **Зэрэгцээ /parallel/ орчны дундын ба хувийн хувьсагч**
Зэрэгцээ орчны хувьсагч дундын эсвэл хувийн аль нь ч байсан болно. Дундын хувьсагчийг паралель мужид тодорхойлохоос гадна бүх хуулбар процесс нэгэн зэрэг хандаж болно. Харин хувийн хувьсагч нь аль ч хуулбар процессоос нуугдмал байдаг. 

Хувьсагчийн анхны төлөв дараах байдлаар тодорхойлогдоно. Үүнд:
* Дундын хувьсагч нь санах ойд статик байдлаар байршина.
* Динамикаар байршсан обьектууд дундын байна.
* Автоматаар хадгалагдсан хувьсагч нь хувийнх байна.

*Дараах кодын хэсэг нь анхдагч дүрмүүдийн жишээг харуулж байна:*

```cpp
int E1;                        /* дундын статик хувьсагч */
void main (argvc,...) {        /* argvc нь дундын */
   int i;                      /* автоматаар дундын хувьсагч болно */
void *p = malloc(...);         /* malloc-аар санах ойд байршина */
                               /* бүх хуулбар процессоос хандах боломжтой */
                               /* ба хувийн байж болохгүй */
#pragma omp parallel firstprivate (p)
   {
     int b;                     /* автоматаар хувийн хувьсагч */
     static int s;              /* статик дундын хувьсагч */

     #pragma omp for
     for (i =0;...) {
       b = 1;                   /* b одоо болтол хувийн хувьсагч! */
       foo (i);                 /* i нь хувийн хувьсагч учир */
                                /* I нь энэ давталтын хувьсагч */
      }
#pragma omp parallel
     {
       b = 1;                   /* b хувьсагч энэ тохиолдолд дундынх */
                                /* учир нь програмын өөр хэсэгт ашиглагдаж байна */
     }
   }
 }
int E2;                         /* статик дундын хувьсагч */ 
void foo (int x) {              /* зэрэгцээ хэсэгт х хувьсагч хувийн */
int c;                          /* */
 ... }
```

Дараах код нь for давталтыг зэрэгцээгээр ажиллуулах жишээ юм. Энэ жишээнд thread_id болон nloops нь хувийн хувьсагч болохыг харж болно.
OpenMP -д for давталтыг зэрэгцээ ажиллуулах нь маш энгийн байдаг. Давталт дахь тоолуурууд (энэ тохиолдолд хувьсагч i) хувийн хувьсагчид байхаар зарлагдсан байна.

```cpp
#include 
#include 
int main(int argc, char **argv) 
{
  int i, thread_id, nloops;
  #pragma omp parallel private(thread_id, nloops) 
  {
    nloops = 0;
     #pragma omp for
     for (i=0; i<1000; ++i) 
     {
        ++nloops; 
     }
    thread_id = omp_get_thread_num();
    printf("Thread %d performed %d iterations of the loop.\n",
           thread_id, nloops ); 
  }
  return 0;  
}
```

Ангилал:Программ хангамж