Int i, j;
i =1; j =2; #pragma omp parallel private(i) firstprivate(j) { i =3; // i - private переменная, значение при входе в параллельную область не // определено, поэтому выполняется инициализация j =i+j; // j - firstprivate переменная, значение при входе в параллельную область // определено и равно 2 } cout<<”i=”<<i<<” j=”<<j<<endl; ………….. // код программы Переменные i и j при выходе из параллельной области сохранят свои оригинальные значения, т.е. значения до входа в параллельную область i=1, j=2. Пример: #pragma omp parallel { #pragma omp for lastprivate(i) //значение i не определено при входе, for (i=0; i<10; i++) // поэтому выполняется инициализация a[i] = b[i] + 1; } a[i-1]=b[i-1];
В значение i в конце параллельной области будет равно 10, как в случае последовательного выполнения цикла. 5. default(shared | none) позволяет установить область видимости переменных. По умолчанию устанавливается shared. Использование default(none) требует, чтобы для каждой переменной в параллельной секции была явно задана область видимости. В директиве parallel может быть определен единственный оператор default. Переменные могут быть исключены из умалчиваемого определения путем использования директив private, firstprivate, lastprivate, reduction и shared, например: #pragma omp parallel for default(shared) firstprivate(i) private(x) private(r) lastprivate(i) 6. shared (список) - объявляет перечисленные в списке переменные общими для всех нитей группы. Т.е. каждая общая переменная существует в одном экземпляре для всей программы и доступна для каждой нити под одним и тем же именем.
Пример: Каждая нить в параллельной области принимает решение, основываясь на номере нити, какую часть массива x обрабатывать. #pragma omp parallel shared(x, npoints) private(iam, np, ipoints) { iam = omp_get_thread_num(); np = omp_get_num_threads(); ipoints = npoints / np; subdomain(x, iam, ipoints); // функция обработки массива x } 7. copyin (список) - выполняет присвоение одного и того же значения переменной, определенной в threadprivate в каждую нить параллельной области. Т.е. для каждой переменной, указанной в операторе copyin, значение переменной из основной нити при воде в параллельную область копируется в приватные копии переменных каждой нити. Ограничения, накладываемые на использование клаузы copyin следующее - переменные, указанные в copyin, должны быть переменными threadprivate. 8. reduction (операция: список) - выполняет редукцию переменных, которые перечислены в списке, с оператором op. Список переменных перечисляется через запятую. Допустимые операции: +, -, *, /, &, |, ||, && Ограничения, накладываемые на использование директивы reduction: 1. Тип переменных должен быть приемлемым для операции редукции, не разрешены типы указателя и ссылки. 2.Переменные, которые указаны в клаузе reduction, не должны быть константами. 3.Переменные, которые указаны в клаузе reduction, должны быть разделяемыми в общем контексте программы. Пример: В данном примере каждая нить имеет свою копию переменной редукции: a и y. После окончания работы выполняется операция редуцирования (в данном случае сложение) всех локальных копий переменных. #pragma omp parallel for reduction(+: a, y) for (i=0; i<n; i++) { a += b[i]; y = sum(y, c[i]); }
|