Загрузка...
     

Параллельное программирование - вопросы2

11.01.11, 10:30
Автор dbimatov

Вопросы ко второй контрольной точке:
1. GRID. Что это такое. 
Достоинства и недостатки по сравнению с суперкомьютерами (например, по сравнению с кластерами).
2. Реконфигурируемые вычислительные системы (FPGA).
Вычисления на графических процессорах (GPGPU).
Достоинства и недостатки по сравнению с вычислителями общего назначения.
3. Параллельный алгоритмы умножения матрицы на вектор.
4. Параллельный алгоритм умножения матрицы на матрицу.
5. Параллельный алгоритм сортировки.
6. Паралелльный алгоритм решения системы линейных уравнений.
7. Параллельный вариант алгоритма Флойда 
(поиск всех кратчайших путей).
8. Реализация классических задач синхронизации.
Необходимо описать, какие способы синхронизации и как используются для решения одной из задач  
а) обедающие философы
б) читатели и писатели
в) спящий парикмахер
г) команда потоков
9. Отладка, оптимизация, профилирование паралелльных программ.
Отличия от последовательных программ. 
Какие инструменты бывают, что позволяют делать.

Комментарии

ответ на 8г)КОМАНДА ПОТОКОВ. Пока еще не сдавал, так что предварительно.
Алгоритм:

В главном потоке:
{
1. Создаем глобальные переменные: для списка заданий и для следующего невыполненного задания.
2. Генерируем задания для потоков.
3. Запускаем все потоки.
4. ждем завершения рабочих потоков
}

В каждом рабочем потоке:
{
lock(locker)
{
читаем следующее задание из списка заданий,
прибавляем 1 к индексу след задания,
если задания в списке закончились завершаем поток
}
выполняем задание
}

обедающие философы:
Используется массив мутексов(mutices), размер равен количеству вилок (N) и собственно массив вилок, в котором хранится ИД филосова, если он её взял и NO_VALUE если она не занята.
В главном цикле создается N потоков-философов, на которые повешена функция phil, В ней в бесконечном цикле вызываются функции eat и think. Функция “Думать” – это просто sleep потока на случайную величину. Самая соль в функции “Есть”.
В ней:
while (не взяли обе вилки)
{
if (не взяли левую)
{
лочим левую вилку (pthread_mutex_lock(&mutices[l]);)
пытаемся взять левую вилку
отпускаем мутекс ( pthread_mutex_unlock(&mutices[l]);)
}
if (не взяли правую)
{
лочим правую вилку pthread_mutex_lock(&mutices®); )
пытаемся взять правую вилку
отпускаем мутекс ( pthread_mutex_unlock(&mutices®); )
}
}

едим случайное количество времени лочим левую вилку (pthread_mutex_lock(&mutices[l]);) отпускаем левую вилку отпускаем мутекс ( pthread_mutex_unlock(&mutices[l]);) лочим правую вилку pthread_mutex_lock(&mutices®); ) отпускаем правую вилку отпускаем мутекс ( pthread_mutex_unlock(&mutices®); )

всио

Рассмотрим парикмахерскую, в которой работает один парикмахер, имеется одно кресло для стрижки и несколько кресел в приемной для посетителей, ожидающих своей очереди. Если в парикмахерской нет посетителей, парикмахер засыпает прямо на своем рабочем месте. Появившийся посетитель должен его разбудить, в результате чего парикмахер приступает к работе. Если в процессе стрижки появляются новые посетители, они должны либо подождать своей очереди, либо покинуть парикмахерскую, если в приемной нет свободного кресла для ожидания. Задача состоит в том, чтобы корректно запрограммировать поведение парикмахера и посетителей.
Одно из возможных решений этой задачи представлено ниже. Процедура barber() описывает поведение парикмахера (она включает в себя бесконечный цикл – ожидание клиентов и стрижку). Процедура customer() описывает поведение посетителя. Несмотря на кажущуюся простоту задачи, понадобится целых 3 семафора: customers – подсчитывает количество посетителей, ожидающих в очереди, barbers – обозначает количество свободных парикмахеров (в случае одного парикмахера его значения либо 0, либо 1) и mutex – используется для синхронизации доступа к разделяемой переменной waiting. Переменная waiting, как и семафор customers, содержит количество посетителей, ожидающих в очереди, она используется в программе для того, чтобы иметь возможность проверить, имеется ли свободное кресло для ожидания, и при этом не заблокировать процесс, если кресла не окажется. Заметим, что как и в предыдущем примере, эта переменная является разделяемым ресурсом, и доступ к ней охраняется семафором mutex. Это необходимо, так как для обычной переменной, в отличие от семафора, чтение и последующее изменение не являются неделимой операцией.
#define CHAIRS 5
typedef int semaphore; /* тип данных «семафор» /
semaphore customers = 0; /
посетители, ожидающие в очереди /
semaphore barbers = 0; /
парикмахеры, ожидающие посетителей /
semaphore mutex = 1; /
контроль за доступом к переменной waiting /
int waiting = 0;
void barber()
{
while (true) {
down(customers); /
если customers == 0, т.е. посетителей нет, то заблокируемся до появления посетителя /
down(mutex); /
получаем доступ к waiting /
waiting = wating – 1; /
уменьшаем кол-во ожидающих клиентов /
up(barbers); /
парикмахер готов к работе /
up(mutex); /
освобождаем ресурс waiting /
cut_hair(); /
процесс стрижки /
}
void customer()
{
down(mutex); /
получаем доступ к waiting /
if (waiting < CHAIRS) /
есть место для ожидания /
{
waiting = waiting + 1; /
увеличиваем кол-во ожидающих клиентов /
up(customers); /
если парикмахер спит, это его разбудит /
up(mutex); /
освобождаем ресурс waiting /
down(barbers); /
если парикмахер занят, переходим в состояние ожидания, иначе – занимаем парикмахера*/
get_haircut(); /* процесс стрижки /
}
else
{
up(mutex); /
нет свободного кресла для ожидания – придется уйти */
}
}

Про эту задачу рассказывалось на одной из лекций, только вместо читателей-писателей были поставщики-потребители (презенташка есть в первой части материалов).
В качестве средства обмена будем использовать циклический буфер (в него можно одновременно читать и писать – для пущего параллелизма).
Для синхронизации будем использовать 2 мьютекса: MutexReader (штоб двое не читали одновременно) и MutexWriter (штоб двое не писали одновременно) + 2 семафора – SemaphoreEmpty (не дает прочитать из пустого буфера) и SemaphoreFull (не дает записать в полный буфер). Одновременно читать и писать в один элемент нам также не дадут семафоры.
В основном потоке создаем ср-ва синхронизации и желаемое количество читателей и писателей.

Писатель()
{
Бесконечный цикл
{
Данные = Долго_подготавливаем_данные();

Забираем единичку у SemaphoreEmpty; // Тут SemaphoreEmpty
Забираем мьютекс MutexWriter;
Кладем_данные_в_буфер(Данные);
Отпускаем мьютекс MutexWriter;
Отдаем единичку в SemaphoreFull; // Тут SemaphoreFull
}
}

Читатель()
{
Бесконечный цикл
{
Забираем единичку у SemaphoreFull; // Тут SemaphoreFull
Забираем мьютекс MutexReader;
Данные = Получаем_данные_из_буфера();
Отпускаем мьютекс MutexReader;
Отдаем единичку в SemaphoreEmpty; // Тут SemaphoreEmpty

Долго_обрабатываем_данные(Данные);
}
}

Вроде всё..

Войдите, чтобы оставить комментарий