Многопоточное программирование

Содержание

Слайд 2

Виды параллелизма.

Общая память

Распределенная
память

Виды параллелизма. Общая память Распределенная память

Слайд 3

Средства параллельного программирования

Средства параллельного программирования

Слайд 4

Треды

Тредами (потоки, лекговесные процессы) называются параллельно выполняющиеся потоки управления в адресном пространстве

Треды Тредами (потоки, лекговесные процессы) называются параллельно выполняющиеся потоки управления в адресном пространстве одного процесса.
одного процесса.

Слайд 5

Треды и процессы

обмен через общую память

обмен через посылку сообщений

Треды и процессы обмен через общую память обмен через посылку сообщений

Слайд 6

Различие тредов и процессов

Различные треды выполняются в одном адресном пространстве.
Различные

Различие тредов и процессов Различные треды выполняются в одном адресном пространстве. Различные
процессы выполняются в разных адресных пространствах.
Треды имеют «собственный» стек и набор регистров. Глобальные данные являются общими.
Как локальные, так и глобальные переменные процессов являются «собственными».

Слайд 7

Средства многопоточного программирования

Треды поддерживаются практически всеми современными операционными системами. Средства для многопоточного

Средства многопоточного программирования Треды поддерживаются практически всеми современными операционными системами. Средства для
программирования встроены в язык Java.
Переносимая библиотека pthreads, разработанная Xavier Leroy, предоставляет средства для создания и управления тредами.

Слайд 8

Создание и завершение тредов

int pthread_create (
pthread_t * outHandle,
pthread_attr_t *inAttribute,

Создание и завершение тредов int pthread_create ( pthread_t * outHandle, pthread_attr_t *inAttribute,
void *(*inFunction)(void *),
void *inArg
);
void pthread_exit(void *inReturnValue)
int pthread_join(
pthread_t inHandle,
void **outReturnValue,
);

pthread_create

pthread_join

pthread_exit

родительский тред

тред-потомок

Слайд 9

Создание треда

int pthread_create ( pthread_t * outHandle, pthread_attr_t *inAttribute,
void *(*inFunction)(void *),

Создание треда int pthread_create ( pthread_t * outHandle, pthread_attr_t *inAttribute, void *(*inFunction)(void
void *inArg);
outHandle – используется для возвращение в тред-родитель идентификатора треда потомка;
inAttribute – атрибуты треда;
inFunction – указатель на функцию, содержащую код, выполняемый тредом;
inArg – указатель на аргумент, передаваемый в тред;

Слайд 10

Завершение треда

void pthread_exit(void *inReturnValue)
Вызов этой функции приводит к завершению треда. Процесс-родитель получает

Завершение треда void pthread_exit(void *inReturnValue) Вызов этой функции приводит к завершению треда.
указатель в качестве возвращаемых данных.
Обычное завершение функции и возврат указателя на void*, выполняемой тредом эквивалентно вызову функции pthread_exit, которая используется в случае, когда надо завершить тред из функций, вызванных этой функцией.

Слайд 11

Обработка завершения треда на треде-родителе

int pthread_join( pthread_t inHandle, void **outReturnValue);
Вызов этой функции

Обработка завершения треда на треде-родителе int pthread_join( pthread_t inHandle, void **outReturnValue); Вызов
приводит к блокировке родительского треда до момента завершения треда-потомка, соответствующего индентификатору inHandle. В область, указанную параметром outReturnValue, записывается указатель, возвращенный завершившимся тредом.
pthread_join приводит к освобождению ресурсов, отведенных на тред (в частности сохранненого возращаемого значения). Необходимо выполнять также для синхронизации основного треда и тредов-потомков.

Слайд 12

Пример: вычисление определенного интеграла

y = f(x)

a

b

xi

xi+1

Si

xi-1

Пример: вычисление определенного интеграла y = f(x) a b xi xi+1 Si xi-1

Слайд 13

#include
#include
#include
double a = 0.0, b = 1.0, h, *r;
int

#include #include #include double a = 0.0, b = 1.0, h, *r;
numt, n;
double f(double x)
{
return 4 / (1 + x * x);
}

Слайд 14

void* worker(void* addr)
{
int my, i;
double s, p;
my =

void* worker(void* addr) { int my, i; double s, p; my =
*(int*)addr;
s = 0.0;
for(p = a + my * h; p < b; p += numt * h)
{
s += h*(f(p) + f(p + h))/2.;
}
r[my] = s;
return (void*)(r + my);
}

Слайд 15

main(int arc, char* argv[])
{
int i;
double S;
pthread_t *threads;
numt =

main(int arc, char* argv[]) { int i; double S; pthread_t *threads; numt
atoi(argv[1]);
n = atoi(argv[2]);
threads = malloc(numt * sizeof(pthread_t));
r = malloc(numt * sizeof(double));
h = (b - a) / n;
for(i = 0; i < numt; i ++)
pthread_create(threads + i, NULL, worker, (void*)&i);
S = 0;
for(i = 0; i < numt; i ++) {
double* r;
pthread_join(threads[i], (void**)&r);
S += *r;
}
printf("pi = %lf\n", S);
}

Слайд 16

Проблема недетерминизма

Программа называется недетерминированной, если при одних и тех же входных данных она может

Проблема недетерминизма Программа называется недетерминированной, если при одних и тех же входных
демонстрировать различное наблюдаемое поведение

Слайд 17

a

read

write

increment

read

increment

write

a = a + 1

a = a + 1

a = 0

a =

a read write increment read increment write a = a + 1
1

Слайд 18

a

read

write

increment

read

increment

write

a = a + 1

a = a + 1

a = 0

a =

a read write increment read increment write a = a + 1
2

Слайд 19

a:=a+1

a:=a+1

a=0

a=2

Неделимой называется операция, в момент выполнения которой состояние общих переменных не может

a:=a+1 a:=a+1 a=0 a=2 Неделимой называется операция, в момент выполнения которой состояние
«наблюдаться» другими тредами

Неделимая операция

Слайд 20

Семафоры

Семафорами называются общие переменные, которые принимают неотрицательные значение целого типа для работы

Семафоры Семафорами называются общие переменные, которые принимают неотрицательные значение целого типа для
с которыми предусмотрены две неделимые операции:
увеличить значение семафора на 1;
дождаться пока значение семафора не станет положительным и уменьшить значение семафора на 1.

Слайд 21

Поддержка семафоров в библиотеке pthreads

sem_t – тип семафора
sem_init(sem_t* semaphor, int flag, int

Поддержка семафоров в библиотеке pthreads sem_t – тип семафора sem_init(sem_t* semaphor, int
value)
semaphor – семафор,
flag – флаг (0 – внутри процесса, 1 – между процессами)
value – начальное значение
sem_post(sem_t* semaphor) – увеличение семафора sem_wait(sem_t* semaphor) – уменьшение семафора

Слайд 22

Кольцевой буфер

front

rear

producer

consumer

Кольцевой буфер front rear producer consumer

Слайд 23

#include
#include
#include
#include
#include
#define N 3
static int buf[N];
static int rear;
static

#include #include #include #include #include #define N 3 static int buf[N]; static
int front;
static sem_t empty;
static sem_t full;
void
init ()
{
front = 0;
rear = 0;
sem_init (&empty, 0, N);
sem_init (&full, 0, 0);
}

Слайд 24

void process(int number)
{
sleep(number);
}
void *
consumer (void *arg)
{
int i = 0;
while

void process(int number) { sleep(number); } void * consumer (void *arg) {
(i != -1)
{
sem_wait (&full);
i = buf[rear];
process(i);
printf ("consumed: %d\n", i);
rear = (rear + 1) % N;
sem_post (&empty);
}
}

Слайд 25

void *
producer (void *arg)
{
int i;
i = 0;
while (i !=

void * producer (void *arg) { int i; i = 0; while
-1)
{
sem_wait (&empty);
printf ("Enter number:");
scanf ("%d", &i);
buf[front] = i;
front = (front + 1) % N;
sem_post (&full);
}
}

Слайд 26

main (int argc, char *argv[])
{
pthread_t pt;
pthread_t ct;
init ();
pthread_create

main (int argc, char *argv[]) { pthread_t pt; pthread_t ct; init ();
(&pt, NULL, producer, NULL);
pthread_create (&ct, NULL, consumer, NULL);
pthread_join (ct, NULL);
pthread_join (pt, NULL);
}

Слайд 27

Критические секции

Критической секцией называется фрагмент кода программы, который может одновременно выполнятся только

Критические секции Критической секцией называется фрагмент кода программы, который может одновременно выполнятся только одним тредом.
одним тредом.

Слайд 28

Пример: создание неделимой опреации

1-й тред:
a = a + 1

2-й тред:
a

Пример: создание неделимой опреации 1-й тред: a = a + 1 2-й
= a + 1

Как сделать операцию a = a + 1 неделимой?

Слайд 29

1-й тред:
while(true) {
while(in2);
in1 = true;
a = a +

1-й тред: while(true) { while(in2); in1 = true; a = a +
1;
in1 = false;
}

2-й тред:
while(true) {
while(in1);
in2= true
a = a + 1;
in2 = false;
}

Слайд 30

Поддержка критических секций в pthreads

«Мютекс» - mutex – mutual exclusion (взаимное исключение);
Объявление

Поддержка критических секций в pthreads «Мютекс» - mutex – mutual exclusion (взаимное
и инициализация:
pthread_mutex_t – тип для взаимного исключения;
pthread_mutex_init(pthread_mutex_t* mutex, void* attribute);
pthread_mutex_destroy(pthread_mutex_t* mutex);
Захват и освобождение мютекса:
pthread_mutex_lock(pthread_mutex_t* mutex);
pthread_mutex_unlock(pthread_mutex_t* lock);
Освобождение мютекса может быть осуществлено только тем тредом, который производил его захват.

Слайд 31

Пример: умножение матриц

C

C = A * B

каждый тред вычисляет свою строку матрицы

Пример: умножение матриц C C = A * B каждый тред вычисляет свою строку матрицы

Слайд 32

Умножение матриц: код программы

#include
#include
#include
pthread_mutex_t mut;
static int N, nrow;
static double

Умножение матриц: код программы #include #include #include pthread_mutex_t mut; static int N,
*A, *B, *C;

Слайд 33

void
setup_matrices ()
{
int i, j;
A = malloc (N * N *

void setup_matrices () { int i, j; A = malloc (N *
sizeof (double));
B = malloc (N * N * sizeof (double));
C = malloc (N * N * sizeof (double));
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
{
A[i * N + j] = 1;
B[i * N + j] = 2;
}
}
void
print_result ()
{
… }

Слайд 34

void *
worker (void *arg)
{
int i, j;
while (nrow < N)
{

void * worker (void *arg) { int i, j; while (nrow {
int oldrow;
pthread_mutex_lock (&mut);
oldrow = nrow;
nrow++;
pthread_mutex_unlock (&mut);

Слайд 35

for (i = 0; i < N; i++)
{
int j;
double t

for (i = 0; i { int j; double t = 0.0;
= 0.0;
for (j = 0; j < N; j++)
t += A[oldrow * N + j] * B[j * N + i];
C[oldrow * N + i] = t;
}
}
return NULL;
}

Слайд 36

main (int argc, char *argv[])
{
int i, nthreads;
pthread_t *threads;
pthread_mutex_init(&mut, NULL);

main (int argc, char *argv[]) { int i, nthreads; pthread_t *threads; pthread_mutex_init(&mut,
nthreads = atoi (argv[1]);
threads = malloc (nthreads * sizeof (pthread_t));
N = atoi (argv[2]);
setup_matrices ();
Имя файла: Многопоточное-программирование.pptx
Количество просмотров: 144
Количество скачиваний: 1