ним имеет доступ каждый из запущенных процессов slave_thr
// и запускающая программа main
// sp, s - локальные переменные процессов slave_thr
sp=0 // указатель локального стека - локальный стек пуст
s=0 // частичная сумма интегралов, вычисленных на отрезках,
// обработанных данной копией процесса
// начало цикла обработки стека интервалов
while(1)
{
// ожидание появления в глобальном стеке интервалов для обработки
sem_wait(sdat.sem_task_present)
// чтение одного интервала из списка интервалов
// Начало критической секции чтения из глобального
// стека очередного интервала интегрирования
//
sem_wait(sdat.sem_list)
sdat.ntask-- // указатель глобального стека
GET_OF_GLOBAL_STACK[sdat.ntask](a,b,fa,fb,sab)
if(sdat.ntask)
sem_post(&sdat.sem_task_present)
if(a<=b) // очередной отрезок не является терминальным
sdat.nactive++ // увеличить число процессов, имеющих
// интервал для интегрирования
sem_post(sdat.sem_list)
//
// Конец критической секции чтения из глобального
// стека очередного интервала интегрирования
if(a>b) // отрезок является терминальным
break // выйти из цикла обработки стека интервалов
// начало цикла интегрирования одного интервала
while(1)
{
c=(a+b)/2
fc=fun(c)
sac=(fa+fc)*(c-a)/2
scb=(fc+fb)*(b-c)/2
sacb=sac+scb
if(!BreakCond(sacb,sab))
{
s+=sacb
if(!sp) // локальный стек пуст
break // выход из цикла интегрирования
// одного интервала
sp--
GET_FROM_LOCAL_STACK[sp]( a, b, fa, fb, sab)
}
else
{
PUT_TO_LOCAL_STACK[sp]( a, c, fa, fc, sac)
sp++
a=c
fa=fc
sab=scb
}
// перемещение части локального стека
// в общий список интервалов
if((sp>SPK) && (!sdat.ntask))
{
// Начало критической секции заполнения глобального
// стека отрезками интегрирования
//
sem_wait(sdat.sem_list)
if(!sdat.ntask)
{
// установить семафор наличия
// записей в глобальном стеке
sem_post(sdat.sem_task_present)
}
while((sp>1) && (sdat.ntask
{
sp--
GET_FROM_LOCAL_STACK[sp](a,b,fa,fb,sab)
PUT_TO_GLOBAL_STACK[sdat.ntask](a,b,fa,fb,sab)
sdat.ntask++
}
sem_post(sdat.sem_list)
//
// Конец критической секции заполнения глобального
// стека отрезками интегрирования
}
}
// конец цикла интегрирования одного интервала
// Начало критической секции заполнения глобального
// стека терминальными отрезками (a>b)
//
sem_wait(&sdat.sem_list)
sdat.nactive--
if( (!sdat.nactive) && (!sdat.ntask) )
{
// запись в глобальный стек списка терминальных отрезков
for(i=0;i {
PUT_TO_GLOBAL_STACK[sdat.ntask](2,1,-,-,-)
sdat.ntask++;
}
// в глобальном стеке есть записи
sem_post(sdat.sem_task_present)
}
sem_post(sdat.sem_list)
//
// Конец критической секции заполнения глобального
// стека терминальными отрезками
}
// конец цикла обработки стека интервалов
// Начало критической секции сложения частичных сумм
//
sem_wait(&(sdat.sem_sum))
sdat.s_all+=s
sem_post(&(sdat.sem_sum))
//
// Конец критической секции сложения частичных сумм
}
PUT_INTO_GLOBAL_STACK[sdat.ntask]
(A,B,fA,fB,sAB)
{
sdat.list_of_tasks[sdat.ntask].a=A;
sdat.list_of_tasks[sdat.ntask].b=B;
sdat.list_of_tasks[sdat.ntask].fa=fA;
sdat.list_of_tasks[sdat.ntask].fb=fB;
sdat.list_of_tasks[sdat.ntask].s=sAB;
}
PUT_FROM_GLOBAL_STACK[sdat.ntask]
(A,B,fA,fB,sAB)
{
A=sdat.list_of_tasks[sdat.ntask].a;
B=sdat.list_of_tasks[sdat.ntask].b;
fA=sdat.list_of_tasks[sdat.ntask].fa;
fB=sdat.list_of_tasks[sdat.ntask].fb;
sAB=sdat.list_of_tasks[sdat.ntask].s;
}
Параллельный алгоритм: метод глобального стека
Введение в параллельные алгоритмы: Параллельные алгоритмы интегрирования функций © Якобовский М.В.
из 40
Москва, 2010 г.