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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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