
Алгоритмы / Поиск минимального разбиения
.docДоклад по теме «Поиск минимального разбиения множества вершин взвешенного графа».
Выполнил Литвинов Михаил.
-
Постановка задачи оптимального разбиения графов
Естественной и адекватной моделью распределения задач по процессорам кластера является взвешенный неориентированный граф G, который задан множеством вершин V и множеством рёбер E: G(V, E). Кроме того, на множестве вершин определена неотрицательная функция F1(V), а на множестве рёбер также неотрицательная функция F2(E). Значения функции F1 называются весами вершин графа, а значения функции F2 – весами рёбер графа. Каждая вершина этого графа представляет собой одну из задач, а вес этой вершины - число операций, выполняемых при решении этой задачи. Вес ребер моделирует коммуникационные затраты на обмен данными между задачами, соответствующими вершинам, соединенным этими ребрами. С помощью этой модели распределение задач по процессорам представляется как разбиение множества вершин графа V на непересекающиеся подмножества, которое порождает разбиение графа G(V,E) на непересекающиеся подграфы. При этом каждый подграф ассоциируется с некоторым процессором, который будет использоваться для решения всех задач, соответствующих вершинам этого подграфа. Таким образом, оптимальное распределение вычислительной нагрузки между доступными процессорами сводится к оптимальному разделению графа G(V, E). Критериями оптимальности могут быть: 1) равенство сумм весов вершин подграфов, 2) минимальность суммы весов ребер, соединяющих вершины, принадлежащие разным подграфам; 3) число подграфов.
Первый критерий обеспечивает баланс вычислительной нагрузки процессоров. Смысл второго критерия состоит в том, что он обуславливает минимум коммуникационных затрат. Наконец, число подграфов определяет число используемых процессоров. Легко видеть, что указанные выше критерии могут противоречить друг другу. Чаще всего в различных постановках задач оптимального разбиения графов один из критериев считается главным, а остальные рассматриваются как ограничения.
Задача оптимального разделения графа является NP – полной и, как показывает анализ состояния исследований в этой области, в общей постановке задача эта задача решается только в узком диапазоне значений параметров k, n, m. На практике обычно оптимальное разделение графа выполняется для некоторого частного случая, например: 1) веса вершин и ребер графа равны 1 и в качестве приоритетного критерия используется либо условие 1, либо условие 2; 2) веса вершин различны, веса ребер равны 0, и в качестве критерия оптимальности используется только условие 1.
Ниже описывается постановка задачи (модель) оптимального разбиения вершин графа, критерий решения которой предполагает балансировку сумм вычислительных нагрузок и коммуникационных затрат, требуемых для решения задач, ассоциированных с каждым процессором. На основе указанной модели предлагается комбинаторный подход к поиску минимального разбиения множества вершин графа G(V, E), основанный на конструктивном перечислении вариантов разбиений указанного множества. Целью этого поиска минимального разбиения множества вершин графа является определение минимального количества процессоров, совокупность которых обеспечивает заданное ускорение.
Пусть задан неориентированный взвешенный граф G(V,E) с числом вершин равным n: V={v1,…,vn}, и числом рёбер равным m: E ={e1,…,em}. Функция F1 ставит в соответствие каждой вершине графа vi ее вес qi, аналогично функция F2 ставит в соответствие каждому ребру графа ei его вес ri. Такой граф определяет, что при использовании одного процессора все задачи могут быть решены в результате выполнения T1 операций, где T1 представляет собой сумму весов всех вершин множества V: T1= F1(V).
Теперь рассмотрим разбиения множества вершин V графа G(V,E) на k непересекающихся подмножеств P={V1,…,Vk}. Этими подмножествами вершин определяются подграфы G1(V1, E1),…, Gk(Vk,Ek), для которых выполняются следующие соотношения:
1) ∀ i,j ∈{1, 2, …, k} (i≠ j) ⇒ Vi ⋂ Vj =∅; 2) V1⋃ V2 ⋃ …⋃Vk=V; 3) n1 + n2 + …+ nk = n, где n1= |V1|, n2=|V2|, …, nk=|Vk|, n=|V|.
Будем считать, что при заданном разбиении число операций выполняемых i-тым процессором определяется как сумма весов вершин i-того подмножества: Qi =∑ F1(Vi). Пусть C (Vi, Vj) множество рёбер, соединяющих вершины из множества Vi с вершинами множества Vj: C (Vi, Vj) = {(u,w)|u∈Vi,w∈Vj}. Тогда сечением Ri по подмножеству Vi графа G(V,E) будем называть совокупность ребер, соединяющих вершины принадлежащие множеству Vi с вершинами, не принадлежащими этому множеству: Ei =⋃j (C (Vi, Vj)), где i≠j. Тогда затраты на передачу и получение информации i-тым процессором можно определить как сумму весов рёбер i-того сечения: Ri= F2 (Ei). Исчисляемое в числе операций время решения всех задач для данного разбиения с использованием k процессоров будет равно: Tk=max((Qi + Ri), где i=1, 2, …, k).
Далее пусть задан требуемый коэффициент ускорения S. Тогда поиск минимального разбиения множества вершин графа G(V,E) сводится к поиску разбиения, минимального по числу непересекающиеся подмножеств P={V1,…,Vk}, для которого выполняются условия достижения заданного ускорения: max((Qi + Ri), где i=1, 2, …, k )≤ T1/S. (1.1)
При этом значение параметра k определяет минимальное число процессоров в многопроцессорной вычислительной системе, которые будут использоваться согласно разбиению P и обеспечат достижение заданного ускорения.
-
Вычислительные схемы метода оптимального разделения графов на основе конструктивного перечисления разбиений множеств их вершин
Минимум функции Tk =max((Qi + Ri), где i=1, 2, …, k), ввиду её монотонности достигается при np=n, np - номер класса эквивалентности разбиений, а n – число вершин в разделяемом графе. (Анализировались все возможные варианты разбиения множества V. Эти варианты разбиений были разбиты на классы эквивалентности, каждый из которых включал в себя разбиения с одинаковым числом подмножеств (np). Это число подмножеств являлось номером соответствующего класса эквивалентности). Пусть, как и прежде, задан неориентированный взвешенный граф G(V,E) с числом вершин равным n. Этот граф является математической моделью решения некоторой задачи. В памяти компьютера этот граф задаётся матрицей смежности вершин A[n][n], диагональные элементы которой представляют собой временную сложность подзадач, которые могут быть решены параллельно на нескольких процессорах или последовательно на однопроцессорной платформе, а все остальные элементы этой матрицы моделируют временные сложности коммуникационных операций. При решении задачи с использованием единственного процессора коммуникационные затраты отсутствуют. И временная сложность решения всей задачи T1 определяется суммой диагональных элементов матрицы A[n][n]: mSA=A[0][0]; for(j1=1;j1<n;j1++)mSA+=A[j1][j1]; положить T1= mSA. Если теперь T1 разделить на заданный коэффициент ускорения S, то мы получим верхнюю границу для значений функции Tk, соответствующих искомым (допустимым) разбиениям. Добавим к этому ограничению условие «использовать минимальное число процессоров» и получим наиболее практически значимую постановку задачи оптимального разделения взвешенного графа: определить разбиение множества вершин графа P={V1,…,Vk}, на минимальное число подмножеств k, такое для которого выполняются условия достижения заданного ускорения (1.1).
Монотонное убывание значений функции Tk при возрастании числа подмножеств в разбиениях позволяет использовать базовый алгоритм Eq2_1 как в вычислительной схеме последовательного поиска (будем отождествлять её с алгоритмом Eq2_1), так и в алгоритме двоичного поиска минимального разбиения взвешенного графа, при котором обеспечивается выполнение условия (1.1). Ниже будем именовать вычислительную схему двоичного поиска алгоритмом Eq3_1.
Сначала рассмотрим псевдокод алгоритма Eq2_1. Он состоит из следующих шагов:
1. Пусть задана матрица A[n][ n] и коэффициент ускорения kp.
2. Вычислить mSA=A[0][0]; for(j1=1;j1<n;j1++)mSA+=A[j1][j1]; mSA/=kp;
3. Установить значения вектора спецификации разбиения pPsi и характеристического вектора pChi в соответствии с разбиением множества X, состоящим из единственного класса, и: for(i=0;i<n;i++) Chi[i]=pPsi[i]=1. Положить ic=0; np= 1.
4. Для анализа первого класса эквивалентности выполнить 5-8:
if(np < 2)
{
5. Проверка, не достаточно ли одного процессора: увеличить значение счётчика и определить текущее (начальное) значение minmaxSA:
ic1++;
for(i=0;i<n;i++) pChi[i]=pPsi[i]=1;
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
6. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата: if(mSA>=maxSA) goto m_result;
7. Выполнить minmaxSA=maxSA;
8. Увеличить текущий номер класса эквивалентности разбиений: np++;}
//************Начало основного цикла
9. Положить nf=n и выполнять 10— 30 для всех оставшихся классов эквивалентности разбиений (np=2, 3, …, n):
while(np<=nf)
{
10. Определить вектор спецификаций для нового класса эквивалентностей разбиений и построить первый характеристический вектор разбиения в этом классе: ii=np; for (i=n-1; i>0; i--)
{if(ii>1){pChi[i]=pPsi[i]=ii; ii--;}else pChi[i]=pPsi[i]=1; }
11. Увеличить значение счётчика и определить minSA:
ic1++;if( ic1>999999999){ic2++;ic1=0;}
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
12. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата: if(mSA>=maxSA) goto m_result;
13. Выполнить: if(minmaxSA>maxSA)minmaxSA=maxSA;
// Переменная minmaxSA позволяет монотонное убывание maxSA
14. Положить :i=n-1;
15. Повторять 16 - 27 пока есть ещё не рассмотренные разбиения в текущем классе эквивалентности :разбиений: while(i>0){
//Change PS***************************
16. Изменить вектор спецификаций, выполнив действия 17-21:
for (i=n-1; i>0; i--) {
17. В текущем классе эквивалентности есть нерассмотренная спецификация?
if((pPsi[i]==pPsi[i-1])&&(pPsi[i]<np))
18. Да, тогда построить новый вектор pPsi:
{pPsi[i]++; pChi[i]=pPsi[i]; k=np;
for(ii=n-1; ii>i; ii--) {pPsi[ii] =k; if(k>pPsi[i]) k--;}
19. Для нового вектора pPsi построить первый характеристический вектор разбиения pCh:
for(ii=1; ii<n; ii++)if(pPsi[ii]==pPsi[ii-1])pChi[ii]=1;else pChi[ii]=pPsi[ii];}
20. Увеличить значение счётчика и определить minSA:
ic1++;if( ic1>999999999){ic2++;ic1=0;}
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
21. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата: if(mSA>=maxSA) goto m_result;
2.2. Выполнить: if(minmaxSA>maxSA)minmaxSA=maxSA;
23. Прервать цикл «for i »: break;} // if(pPsi[i]==pPsi[i-1])&&pPsi[i]<np)
} //end for i
24. Если цикл «for i» был прерван (был построен новый вектор pPsi), то выполнить построение нового характеристического вектора pChi (действия 25 - 29): if(i>0) {
25. Выполнить: ii=n-1;
while(ii>0) { if(pChi[ii]<pPsi[ii]) {pChi[ii]++; k=ii; k++;
while(k<n) { if(pPsi[k]==pPsi[k-1]) {pChi[k]=1; } k++;}
ii=n-1;
26. Увеличить значение счётчика и определить minSA:
ic1++;if( ic1>999999999){ic2++;ic1=0;}
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
27. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата: if(mSA>=maxSA) goto m_result;
28. if(minmaxSA>maxSA)minmaxSA=maxSA;
}//end if(pChi[j]<pPsi[j])
29. Выполнить: else ii--;
}// end while(ii>0)
// Конец изменений pChi
}// end if(i>0)
} //end while(i>0)
30. Выполнить:np++;
}//end while(np<=n)
//*********************Конец основного цикла
m_result: 31. Выполнить:
finish = clock();duration = (double)(finish - start) / CLOCKS_PER_SEC;
32. Вывести номер экспериментальной точки "N= jj ", число просмотренных вариантов "NN= ic2* ic1”, время поиска минимального разбиения множества вершин "duration", номер класса эквивалентности "np", в котором найдено решение, значение функции "Tk=maxSA", характеристический вектор разбиения множества вершин "pChi", который представляет собой найденное решение.
33. Стоп.//Конец описания алгоритма.
Разработка алгоритма Eq3_1 состояла в объединении имеющей общее назначение вычислительной схемы двоичного поиска и поиска экстремального разбиения множества, которая была выше и алгоритма вычисления функции F3. Ниже приводится псевдокод этого алгоритма.
1. Пусть задана матрица A[n][ n] и коэффициент ускорения kp.
2. Вычислить mSA=A[0][0]; for(j1=1;j1<n;j1++)mSA+=A[j1][j1]; mSA/=kp;
3. Выполнить: ic1=ic2=0;np=1;
4. Вывести " mSA=”, inSA ;
5. Выполнить: start = clock();
6. Выполнить генерацию первого разбиения: for(i=0;i<n;i++) pChi[i]=pPsi[i]=1;
7. Обработать первое разбиение, выполнив действия 8 - 10:
if(np < 2)
{
8. Выполнить: for(i=0;i<n;i++) pChi[i]=pPsi[i]=1;
ic1++;
9. Вычислить значение функции S= maxSA для первого разбиения: maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
10. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата:
if(minSA>=maxSA){ minmaxSA=maxSA;minnp=np;
for(j1=0; j1<n; j1++) minpChi[j1]= pChi[j1];
goto m3_result;}
} // if(np < 2)
//************Начало основного цикла
11. Вычислить np : nn1=2; nn2=n; np=(nn1+nn2)/2;
12. Выполнить:
while(nn2>nn1)
{// Изменить pPsi*****************************
13. Определить вектор спецификаций для нового класса эквивалентностей разбиений и построить первый характеристический вектор разбиения в этом классе: ii=np; for (i=n-1; i>0; i--){ if(ii>1){pChi[i]=pPsi[i]=ii; ii--;}else pChi[i]=pPsi[i]=1; }
14. Увеличить значение счётчика и определить minSA:
ic1++;if( ic1>999999999){ic2++;ic1=0;}
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
15. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата:
if(mSA>=maxSA){ minmaxSA=maxSA;minnp=np;
for(j1=0; j1<n; j1++) minpChi[j1]= pChi[j1]; goto m2_result;}
16. Положить: i=n-1;
17. Повторять 18 - 27 пока есть ещё не рассмотренные разбиения в текущем классе эквивалентности:
while(i>0)
{
//Change PS***************************
18. Изменить вектор спецификаций, выполнив действия 19-23:
for (i=n-1; i>0; i--)
{
19. В текущем классе эквивалентности есть нерассмотренная спецификация?
if((pPsi[i]==pPsi[i-1])&&(pPsi[i]<np))
20. Да, тогда. Построить новый вектор pPsi:
{pPsi[i]++; pChi[i]=pPsi[i]; k=np;
for(ii=n-1; ii>i; ii--) {pPsi[ii] =k; if(k>pPsi[i]) k--;}
21. Для нового вектора pPsi построить первый характеристический вектор разбиения pCh:
for(ii=1; ii<n; ii++){if(pPsi[ii]==pPsi[ii-1])pChi[ii]=1;else pChi[ii]=pPsi[ii];} 22. Увеличить значение счётчика и определить minSA:
ic1++;if( ic1>999999999){ic2++;ic1=0;}
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
23. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата:
if(mSA>=maxSA){ minmaxSA=maxSA;minnp=np;
for(j1=0; j1<n; j1++) minpChi[j1]= pChi[j1];
goto m2_result;}
24. Выполнить: break; } // if(pPsi[i]==pPsi[i-1])&&pPsi[i]<np)
} //end for i
25. Если цикл «for i» был прерван (был построен новый вектор pPsi), то выполнить построение нового характеристического вектора pChi (действия 26 – 29): if(i>0)
{
26. Выполнить ii=n-1; while(ii>0)
{ if(pChi[ii]<pPsi[ii]) {pChi[ii]++; k=ii; k++;
while(k<n){if(pPsi[k]==pPsi[k-1]) {pChi[k]=1; }k++;}
ii=n-1;
27. Увеличить значение счётчика и определить minSA:
ic1++;if( ic1>999999999){ic2++;ic1=0;}
maxSA=0; for(j1=0; j1<np; j1++)SA[j1]=0;
for(j1=0; j1<np; j1++){for(j2=0; j2<n; j2++){
if((j1+1)==pChi[j2]){SA[j1]+=A[j2][j2];
for(j3=0; j3<n; j3++)if(pChi[j3]!=(j1+1))SA[j1]+= A[j2][j3];}}
if(maxSA<SA[j1])maxSA=SA[j1];}
28. Если найдено разбиение, обеспечивающее требуемое ускорение, то перейти к обработке результата:
if(mSA>=maxSA){ minmaxSA=maxSA;minnp=np;
for(j1=0; j1<n; j1++) minpChi[j1]= pChi[j1];
goto m2_result;}
}//end if(pChi[j]<pPsi[j])
29. Выполнить: else ii--;
}// end while(ii>0)
//Конец изменений pChi
}// end if(i>0)
} //end while(i>0)
30. Вычислить новое значение np: m2_result:if(mSA>=maxSA)nn2=np; else nn1=np+1; np=(nn1+nn2)/2;
}//end while(nn2>nn1)
//End main cycle
31. Выполнить: m3_result:finish = clock();duration = (double)(finish - start) / CLOCKS_PER_SEC;
32. Вывести номер экспериментальной точки " N= jj ", число просмотренных вариантов "NN= ic2* ic1”, время поиска минимального разбиения множества вершин "duration", номер класса эквивалентности "np", в котором найдено решение, значение функции "S=maxSA", характеристический вектор разбиения множества вершин "minpChi", который представляет собой найденное решение.
33. Стоп.//Конец описания алгоритма
-
Выводы
В результате вычислительного эксперимента выявлено, что минимальное значение временной сложности параллельных вычислений (функция Tk) монотонно убывает с увеличением номера класса эквивалентности разбиений множества вершин взвешенного графа. Эта монотонность имеет места при достаточно широком диапазоне изменений основных параметров, от которых зависит функция Tk. Монотонность функции Tk позволила использовать базовый алгоритм Eq2_1 как в вычислительной схеме последовательного поиска (будем отождествлять её с алгоритмом Eq2_1) так и в алгоритме двоичного поиска минимального разбиения взвешенного графа, при котором обеспечивается коэффициент ускорения в среднем равный 1,665766. Разработанный метод оптимального разделения взвешенных графов, основанный на использовании алгоритма Eq3_1, обеспечивает эффективное решение задачи определения минимального числа процессоров, необходимых для реализации параллельных вычислений с заданным ускорением относительно последовательных вычислений.
-
Пример
Определение минимального числа процессоров p, обеспечивающих заданное ускорение Sp.
Пусть временная сложность 4 задач (подзадач) и возможные затраты времени на передачу сообщений между этими задачами заданы матрицей смежности взвешенного графа G(V,E), приведенной в табл.1:
Табл.1
№/№ |
1 |
2 |
3 |
4 |
1 |
130 |
30 |
30 |
70 |
2 |
30 |
210 |
40 |
30 |
3 |
30 |
40 |
160 |
20 |
4 |
70 |
30 |
20 |
140 |
При этом T1 = 130+ 210 + 160 + 140= 640. Пусть требуемое ускорение Sp=2, (T1/Sp)=320. Тогда если, при наличии в разбиении k блоков, выполняется Tkmax <= T1/Sp, то p=k.
-
Проверяем достижимость:
Пусть k=4, тогда выполняется Tkmax=max(130+30+30+70=260, 210+30+40+30=310, 130+20+40+20=250, 120+50+20+20=260 ) =310, т.е. при k =4 решение существует.
-
Выполним поиск минимального значения k, при котором выполняется Tkmax <= T1/Sp (см. табл 2).
Табл. 2
№ |
PS |
CH |
k |
Tk1 |
Tk2 |
Tk3 |
Tk4 |
Tkmax |
Tkmax<T1/ Sp |
1 |
1111 |
1111 |
1 |
640 |
0 |
0 |
0 |
640 |
0 |
2 |
1112 |
1112 |
2 |
500+130 |
140+130 |
0 |
0 |
630 |
0 |
3 |
1122 |
1121 |
2 |
480+90 |
160+90 |
0 |
0 |
570 |
0 |
4 |
1122 |
1122 |
2 |
340+210 |
300+210 |
0 |
0 |
550 |
0 |
5 |
1222 |
1211 |
2 |
430+100 |
210+100 |
0 |
0 |
530 |
0 |
6 |
1222 |
1212 |
2 |
290+220 |
350+220 |
0 |
0 |
570 |
0 |
7 |
1222 |
1221 |
2 |
270+80 |
370+80 |
0 |
0 |
400 |
0 |
8 |
1222 |
1222 |
2 |
130+130 |
340+130 |
0 |
0 |
470 |
0 |
9 |
1123 |
1123 |
3 |
340+170 |
160+90 |
140+120 |
0 |
510 |
0 |
10 |
1223 |
1213 |
3 |
290+160 |
210+100 |
140+120 |
0 |
450 |
0 |
11 |
1223 |
1223 |
3 |
130+130 |
370+110 |
140+120 |
0 |
480 |
0 |
12 |
1233 |
1231 |
3 |
270+110 |
210+100 |
160+90 |
0 |
380 |
0 |
13 |
1233 |
1232 |
3 |
130+130 |
350+160 |
160+90 |
0 |
510 |
0 |
14 |
1233 |
1233 |
3 |
130+130 |
210+100 |
300+170 |
0 |
470 |
0 |
15 |
1234 |
1234 |
4 |
130+130 |
210+100 |
160+90 |
140+120 |
310 |
1 |
Минимальное количество процессоров, обеспечивающих Sp=2, составляет p=k=4.