Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Параллельная обработка данных лабраб.doc
Скачиваний:
43
Добавлен:
25.03.2016
Размер:
483 Кб
Скачать
☆

Клеточная модель "игра жизнь" дж. Конвея Описание работы

Клеточная модель представляет собой множество клеток (ячеек таблицы), принимающих одно из нескольких состояний. Состояние каждой клетки определяется состоянием её ближайших соседей. Од­ной из известных моделей является "Игра Жизнь" математика Дж. Конвея.

В модели Конвея каждая клетка может находиться в двух состоя­ниях: живая или неживая. Состояние клетки на следующем шаге оп­ределяется потенциалом клетки (числом живых соседних клеток):

  • если потенциал клетки равен двум, то клетка сохраняет свое состояние;

  • если потенциал равен трем, то клетка оживает;

  • если потенциал меньше двух или больше трех, то клетка поги­бает.

Правила изменения состояния клетки можно описать следующим лямбда-выражением:

varlifeRules = new Func<int, bool, bool>((p, state) =>

{

if(p ==3) return true; else if (p ==2) return state; else

return false;

});

Последовательный алгоритм расчета представляет собой расчет состояния каждой клетки:

LifeTabletableNew = new LifeTable; for(inti=0; i< Height; i++) for(intj=0; j < Width; j++)

{

p = CalcPotential(table[i,j]);

tableNew[i, j] = lifeRules(p, table[i,j]);

}

table = tableNew;

Потенциал клетки вычисляется по восьми ближайшим соседям клетки.

intCalcPotential(inti, int j)

{

int p=0;

for(intx = i-1; x <= i + 1; x++) for (int у =j-l; у <=j + l;y++)

{

if(x <0||j<0||x> = Height \ у > = Width | (x == i&&у ==j)) continue;

if(table[x,y]) p++;

}

returnp;

}

Вычисления новых состояний для каждой клетки являются неза­висимыми и могут выполняться параллельно.

Parallel.For(0, Height, (i) => { for(intj=0; j < Width; j++)

{

p = CalcPotential(table[i,j]); tableNew[i, j] = lifeRules(p, table[i,j]);

}

});

Также можно изменить порядок расчета и распараллелить внеш­ний цикл по столбцам:

Parallel. For(0, Width, (j) => { for(inti=0; i< Height; i++)

{

р = CalcPotential(table [i,j]); tctbleNew[i, j] = lifeRules(p, table[i,j]);

}}

Вывод таблицы состояний клеточной модели может быть сле­дующим:

Рисунок 5.1.

ЗАДАНИЯ К ЛАБОРАТОРНОЙ РАБОТЕ № 5

  1. Реализуйте Windows-приложение, которое последовательно отображает состояния клеточной модели "Игра жизнь".

  2. Реализуйте последовательный алгоритм расчета состояний модели.

  3. Реализуйте параллельные алгоритмы расчета состояний моде­ли. Для распараллеливания используйте задачи (tasks) или метод Parallel.For.

  1. Реализуйте возможность отмены расчета с помощью объекта CancellationToken.

  2. Выполните анализ эффективности разработанных алгоритмов.

КОНТРОЛЬНЫЕ ВОПРОСЫ

  1. Имеет ли смысл распараллеливание внутреннего цикла расче­та? Почему?

for(inti=0; i< Height; i++)

{

Parallel.For(0, Width, j=>

{

p = CalcPotential(table[i,j]); tableNew[i, j] = lifeRules(p, table[i,j]);

});

}

  1. Как вариант расчета - по строкам или по столбцам - более эф­фективен и с чем это связано?

  2. Продумайте вариант блочной декомпозиции, где блок высту­пает матрицей размера К х К. В чем достоинства и недостатки блоч­ной декомпозиции для этой задачи? Какое значение параметра К сле­дует выбирать?

ЛАБОРАТОРНАЯ РАБОТА № 6

РАСПАРАЛЛЕЛИВАНИЕ ПРОГРАММЫ ЫЧИСЛЕНИЯ ОПРЕДЕЛЕННОГО ИНТЕГРАЛА С ПОМОЩЬЮ ОрепМР

Цель работы - распараллеливание программ с помощью ОрепМР.

Параллельная ОрепМР-программа состоит из последовательных и параллельных секций. Границы параллельных секций обозначаются директивами ОрепМР. Процесс разработки ОрепМР-программы включает следующие этапы:

  • Разработка последовательной программы;

  • Выявление участков потенциального параллелизма. Чаще все­го это циклы;

  • Анализ трудоемкости параллельных секций (профилирование программы). Наибольший выигрыш в производительности дает рас­параллеливание секций, на которые приходятся наибольшие затраты процессорного времени;

  • Пошаговое распараллеливание программы, начиная с наиболее трудоемких секций.

Профилирование может производиться как с помощью специаль­ных программных инструментов, так и простыми средствами, напри­мер, с помощью вызова специальных подпрограмм-таймеров, разме­щенных в различных местах программы.

Цикл эффективно распараллеливается, если отсутствуют перекре­стные зависимости между его итерациями. Избавиться от таких зави­симостей иногда можно, выполнив преобразование цикла.

Необходимо правильно определить область видимости перемен­ных в параллельных секциях программы. Параметр цикла, например, должен быть объявлен локальной переменной. Инвариант цикла (ве­личина, не изменяющаяся при выполнении итераций цикла) должен быть глобальным.

При вычислении суммы, например, к переменной, которая ис­пользуется для "накопления" суммы, должна быть применена опера­ция приведения (редукции).

Следует обратить внимание на синхронизацию вычислений. По умолчанию в циклах используется барьерная синхронизация. Наличие синхронизаций увеличивает предсказуемость поведения программы, но замедляет ее работу.

Дополнительный выигрыш в производительности дает объедине­ние нескольких параллельных секций в одну. В этом случае умень­шаются накладные расходы на запуск нитей и их завершение.