Справочник от Автор24
Поделись лекцией за скидку на Автор24

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

  • ⌛ 2018 год
  • 👀 414 просмотров
  • 📌 370 загрузок
  • 🏢️ СФУ
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Многопоточное программирование POSIX Threads» pdf
Лекция 4 Многопоточное программирование POSIX Threads (1) Курносов Михаил Георгиевич E-mail: mkurnosov@gmail.com WWW: www.mkurnosov.net Курс «Параллельные вычислительные технологии» Сибирский государственный университет телекоммуникаций и информатики (г. Новосибирск) Весенний семестр, 2018 CC-BY Средства многопоточного программирования Прикладные библиотеки ▪ ▪ ▪ ▪ ▪ Языки программирования ▪ OpenMP (C/C++/Fortran) ▪ Intel Cilk Plus ▪ С++11 Threads ▪ C11 Threads Intel Threading Building Blocks (TBB) Microsoft Concurrency Runtime Apple Grand Central Dispatch Boost Threads Qthread, MassiveThreads ▪ ▪ ▪ ▪ OpenMP C# Threads Java Threads Erlang Threads Haskell Threads Системные библиотеки (System libraries) Уровень пользователя (User space) POSIX Threads Thread Thread Уровень ядра (Kernel space) Win32 API/.NET Threads Thread Thread Thread Apple OS X Cocoa, Pthreads Thread Thread … Thread Системные вызовы (System calls) Kernel thread Kernel thread Kernel thread Kernel thread Kernel thread Kernel thread Kernel thread … Process scheduler Операционная система GNU/Linux, Microsoft Windows, Apple OS X, IBM AIX, Oracle Solaris, … Hardware (Multi-core processor, SMP/NUMA) pthreads (glibc) Kernel thread clone() (Linux syscall) Процессы и потоки Стек потока 0 Стек потока 1 … Стек потока N - 1 Куча (heap) (динамически выделяемая память: malloc/free) Область неинициализированных данных (BSS) (глобальные неинициализированные переменные) Область инициализированных данных (Data) (глобальные инициализированные переменные) Поток 0 int fun() { // … } Поток 1 int fun() { // … } Поток N-1 … int fun() { // … } ▪ Программа (program) – исполняемый файл в определенном формате o GNU/Linux – ELF o Microsoft Windows – PE o Apple maxOS – Mach-O ▪ Процесс (process) – экземпляр запущенной программы ▪ Виртуальное адресное пространство (address space) ▪ Главный поток выполнения (thread) ▪ Поток выполнения (thread) – код и локальная область памяти для хранения данных: стек и TLS – thread local storage Программы и процессы #include const int globalConst = 100; int globalVar = 10; int globalVarNI; int main() { int stackVar = 10; static int staticVar = 100; printf("Hello, World!\n"); return 0; } $ gcc –o prog ./prog.c # Символы исполняемого файла $ objdump --syms ./prog ./prog: file format elf64-x86-64 SYMBOL TABLE: 00000000004005b0 0000000000601024 0000000000601028 00000000004004f6 0000000000601030 g g l g g O O O F O .rodata .data .data .text .bss 0000000000000004 0000000000000004 0000000000000004 0000000000000020 0000000000000004 globalConst globalVar staticVar.2214 main globalVarNI ▪ Исполняемый файл содержит секции, которые сформированы компилятором (gcc) и компоновщиком (ld) o o o o .rodata – глобальные константы .data – инициализированные глобальные переменные .bss – неинициализированные глобальные переменные .text – код программы ▪ При запуске программы секции загружаются в память процесса Программы и процессы #include const int globalConst = 100; int globalVar = 10; int globalVarNI; int main() { int stackVar = 10; static int staticVar = 100; int stackArray[10000000]; return 0; } $ ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 61834 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 61834 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited $ ./prog Segmentation fault (core dumped) ▪ Размер стека главного потока равен 8 KiB (8 * 1024 * 1024 / 4 элементов типа int, 4 * 1024 * 1024) ▪ В программе создан автоматический массив из 10 000 000 элементов Процессы и потоки Стек потока 0 // Uninitialized data (BSS) int sum[100]; // BSS Стек потока 1 … // Initialized data (Data) float grid[100][100] = {1.0}; Стек потока N - 1 Куча (heap) (динамически выделяемая память: malloc/free) Область неинициализированных данных (BSS) (глобальные неинициализированные переменные) int main() { // Local variable (stack) double s = 0.0; // Allocate from the heap float *x = malloc(1000); // ... free(x); Область инициализированных данных (Data) (глобальные инициализированные переменные) Поток 0 int fun() { // … } Поток 1 int fun() { // … } Поток N-1 … int fun() { // … } } Стандарт POSIX Threads ▪ POSIX.1c: Threads extensions (IEEE Std 1003.1c-1995) – определяет API для управления потоками  Thread Creation, Control, and Cleanup  Thread Scheduling  Thread Synchronization  Signal Handling ▪ The Single UNIX Specification // http://www.unix.org/version4/ ▪ Реализации POSIX Threads  FreeBSD, NetBSD, OpenBSD, GNU/Linux, Apple OS X, Solaris  Windows Services for UNIX (POSIX subsystem), pthreads-w32, mingw-w64 pthreads ▪ man pthread ▪ man nptl Модель fork-join управления потоками Thread 0 Fork Fork Join Join Thread 1 ▪ Join – ожидание одним потоком завершения другого (объединение потоков управления) Fork Thread 2 Fork Thread 3 Thread 4 (detached) Время ▪ Fork – создание нового потока Модель fork-join управления потоками Email Client (GUI thread + data process thread) Thread 0 Drawing GUI Fork Terminate Thread 1 Loading emails in background Time Модель fork-join управления потоками Multithreaded HTTP-server Master thread + 1 thread per request Thread 0 Accepting requests Fork Worker thread Loading HTML-document and sending response Time Модель fork-join управления потоками Multithreaded HTTP-server Master thread + thread pool Thread 0 Queue of requests Terminate Fork Worker thread Processing requests from the queue Time Модель fork-join управления потоками Recursive Parallelism – Divide & Conquer (Parallel QuickSort, Reductions, For loops) fib(4) fib(3) fib(2) fib(1) fib(0) fib(2) fib(1) fib(1) fib(0) function fib(int n) if n < 2 then return n x = fork threadX fib(n - 1) y = fork threadY fib(n - 2) join threadX join threadY return x + y end function Обзор POSIX Threads #include int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); int pthread_join(pthread_t thread, void **retval); int pthread_attr_init(pthread_attr_t *attr); int pthread_cancel(pthread_t thread); pthread_t pthread_self(void); int pthread_equal(pthread_t t1, pthread_t t2); Hello, World of POSIX Threads! #include #include void *thread_func(void *arg) { // Код дочернего потока pthread_t tid = pthread_self(); printf("Hello from slave thread %u\n", (unsigned int)tid); sleep(5); return NULL; } $ gcc -Wall -pthread ./prog.c –oprog $ ./prog Hello from master thread 1971812096 Hello from slave thread 1963546368 Поток завершается при: ▪ Вызове в нем pthread_exit() ▪ Выходе из функции потока int main() { ▪ Отмене вызовом pthread_cancel() pthread_t tid; int rc = pthread_create(&tid, NULL, thread_func, NULL); ▪ При вызове exit() все потоки процесса if (rc != 0) { принудительно завершаются fprintf(stderr, "Can't create thread\n"); (например, при выходе из main()) exit(EXIT_FAILURE); } printf("Hello from master thread %u\n", (unsigned int)pthread_self()); // Мастер-поток ожидает завершение дочернего потока pthread_join(tid, NULL); return 0; } Hello, World of POSIX Threads! #include #include $ gcc -Wall -pthread ./prog.c –oprog void *thread_func(void *arg) $ ./prog { Hello from master thread 4256687872 // Код дочернего потока Hello from slave thread 4248422144 pthread_t tid = pthread_self(); printf("Hello from slave thread %u\n", (unsigned int)tid); sleep(5); return NULL; $ ps -L -o comm,pid,lwp,nlwp,psr,pmem,pcpu -C prog } COMMAND prog prog PID LWP NLWP PSR %MEM %CPU 18357 18357 2 1 0.0 0.0 18357 18358 2 0 0.0 0.0 int main() { pthread_t tid; int rc = pthread_create(&tid, NULL, thread_func, NULL); if (rc != 0) { fprintf(stderr, "Can't create thread\n"); exit(EXIT_FAILURE); } printf("Hello from master thread %u\n", (unsigned int)pthread_self()); // Мастер-поток ожидает завершение дочернего потока pthread_join(tid, NULL); return 0; }  LWP – thread id  NLWP – число потоков процесса  PSR – номер процессора Запуск N потоков int main(int argc, char **argv) $ ./prog { Launching 4 threads int nthreads = argc > 1 ? atoi(argv[1]) : 4; pthread_t *tids = malloc(sizeof(*tids) * nthreads); Hello from slave thread 2625984256 if (tids == NULL) { Hello from slave thread 2617591552 fprintf(stderr, "No enough memory\n"); Hello from master thread 2634249984 exit(EXIT_FAILURE); Hello from slave thread 2609198848 } Hello from slave thread 2600806144 printf("Launching %d threads\n", nthreads); for (int i = 0; i < nthreads; i++) { if (pthread_create(&tids[i], NULL, thread_func, NULL) != 0) { fprintf(stderr, "Can't create thread\n"); exit(EXIT_FAILURE); } } // Now we have nthreads + 1 master thread printf("Hello from master thread %u\n", $ ps -L -o comm,pid,lwp,nlwp,psr,pmem,pcpu -C prog (unsigned int)pthread_self()); for (int i = 0; i < nthreads; i++) pthread_join(tids[i], NULL); free(tids); return 0; } COMMAND prog prog prog prog prog PID 18697 18697 18697 18697 18697 LWP NLWP PSR %MEM %CPU 18697 5 1 0.0 0.0 18698 5 2 0.0 0.0 18699 5 2 0.0 0.0 18700 5 0 0.0 0.0 18701 5 0 0.0 0.0 Формула средних прямоугольников (midpoint rule) для вычисления определенного интеграла double func(double x) { return exp(-x * x); } f(x) Второй порядок точности int main(int argc, char **argv) { const double a = -4.0; const double b = 4.0; const int n = 100; a x0 double h double s for (int s += s *= h; x x1 x2 … xn-1 b xn = (b - a) / n; = 0.0; i = 0; i < n; i++) func(a + h * (i + 0.5)); printf("Result Pi: %.12f\n", s * s); return 0; } Параллельный алгоритм интегрирования методом средних прямоугольников (midpoint rule) ▪ Каждый поток вычисляет частичную сумму (часть площади по кривой) f(x) ▪ После чего, результаты суммируются (свойство аддитивности интеграла) double func(double x) { return exp(-x * x); } int main(int argc, char **argv) { const double a = -4.0; const double b = 4.0; const int n = 100; a x0 double h double s for (int s += s *= h; x x1 x2 … xn-1 b xn = (b - a) / n; = 0.0; i = 0; i < n; i++) func(a + h * (i + 0.5)); printf("Result Pi: %.12f\n", s * s); return 0; } Параллельный алгоритм интегрирования методом средних прямоугольников (midpoint rule) 1. Итерации цикла for распределяются между потоками 2. Каждый поток вычисляет часть суммы (площади) 3. Суммирование результатов потоков (во всех или одном) double func(double x) { return exp(-x * x); } int main(int argc, char **argv) { const double a = -4.0; const double b = 4.0; const int n = 100; Варианты распределения итераций (точек) между потоками: 1) Разбиение на p смежных непрерывных частей T0 T0 T0 T0 T1 TID 0 T1 T1 T1 T2 T2 T2 double h double s for (int s += s *= h; T2 TID 2 TID 1 = (b - a) / n; = 0.0; i = 0; i < n; i++) func(a + h * (i + 0.5)); 2) Циклическое распределение итераций по потокам T0 T1 T2 T0 T1 T2 T0 TID 0, TID 1, TID 2, TID 0, TID 1, TID 2, ... T1 T2 T0 T1 printf("Result Pi: %.12f\n", s * s); return 0; T2 } Параллельный алгоритм интегрирования методом средних прямоугольников (midpoint rule) double func(double x) { return exp(-x * x); } Каждому потоку необходимо передать: ▪ порядковый номер потока ▪ число потоков ▪ h, n, a int main(int argc, char **argv) { const double a = -4.0; const double b = 4.0; const int n = 100; double h double s for (int s += s *= h; lb T0 T0 T0 TID 0 T0 T1 printf("Result Pi: %.12f\n", s * s); return 0; ub T1 T1 TID 1 T1 = (b - a) / n; = 0.0; i = 0; i < n; i++) func(a + h * (i + 0.5)); T2 T2 T2 TID 2 T2 } Интегрирование методом средних прямоугольников (midpoint rule) struct thread_data { pthread_t tid; int threadno; int nthreads; }; // Порядковый номер потока 0, 1, 2, … // Количество потоков int main(int argc, char **argv) { int nthreads = (argc > 1) ? atoi(argv[1]) : 2; printf("Numerical integration (%d threads): [%f, %f], n = %d\n", nthreads, a, b, n); struct thread_data *tdata = malloc(sizeof(*tdata) * nthreads); if (tdata == NULL) { fprintf(stderr, "No enough memory\n"); exit(EXIT_FAILURE); } for (int i = 1; i < nthreads; i++) { // Запуск nthreads – 1 потоков! tdata[i].threadno = i; tdata[i].nthreads = nthreads; if (pthread_create(&tdata[i].tid, NULL, integrate, &tdata[i]) != 0) { fprintf(stderr, "Can't create thread\n"); exit(EXIT_FAILURE); } } tdata[0].threadno = 0; tdata[0].nthreads = nthreads; integrate(&tdata[0]); // Мастер-поток участвует в вычислениях, всего nthreads потоков Интегрирование методом средних прямоугольников (midpoint rule) // продолжение main() for (int i = 1; i < nthreads; i++) pthread_join(tdata[i].tid, NULL); free(tdata); printf("Result Pi: %.12f\n", s * s); return 0; } Интегрирование методом средних прямоугольников (midpoint rule) const double a = -4.0; const double b = 4.0; const int n = 10000000; // Глобальная сумма double s = 0.0; double func(double x) { return exp(-x * x); } void *integrate(void *arg) { struct thread_data *p = (struct thread_data *)arg; double h = (b - a) / n; int points_per_proc = n / p->nthreads; int lb = p->threadno * points_per_proc; int ub = (p->threadno == p->nthreads - 1) ? (n - 1) : (lb + points_per_proc - 1); for (int i = lb; i < ub; i++) s += func(a + h * (i + 0.5)); s *= h; // Обновление глобальной суммы return NULL; } // Вся суть распараллеливания – цикл распределен между потоками lb T0 T0 T0 TID 0 T0 T1 ub T1 T1 TID 1 T1 T2 T2 T2 TID 2 T2 Интегрирование методом средних прямоугольников (midpoint rule) struct thread_data { pthread_t tid; int threadno; int nthreads; }; // Порядковый номер потока 0, 1, 2, … // Количество потоков int main(int argc, char **argv) { Ошибка – при каждом запуске результат другой! int nthreads = (argc > 1) ? atoi(argv[1]) : 2; printf("Numerical integration (%d threads): [%f, %f], n = %d\n", nthreads, a, b, n); ./integrate Numerical integration (2 threads): [-4.000000, 4.000000], n = 10000000 struct thread_data *tdata = malloc(sizeof(*tdata) * nthreads); if (tdata == NULL) { Result Pi: 0.638820620709 fprintf(stderr, "No enough memory\n"); exit(EXIT_FAILURE); ./integrate } Numerical integration (2 threads): [-4.000000, for (int i = 1; i < nthreads; i++) { // Запуск nthreads – 1 потоков! Result Pi: 0.000000000001 tdata[i].threadno = i; tdata[i].nthreads = nthreads; ./integrate if (pthread_create(&tdata[i].tid, NULL, integrate, &tdata[i]) != 0) { fprintf(stderr, "Can'tNumerical create thread\n"); integration (2 threads): [-4.000000, exit(EXIT_FAILURE); Result Pi: 1.724699625421 } } ./integrate tdata[0].threadno = 0; tdata[0].nthreads = nthreads; Numerical integration (2 threads): [-4.000000, Result Pi: // 0.701209910269 integrate(&tdata[0]); Мастер-поток участвует в вычислениях, 4.000000], n = 10000000 4.000000], n = 10000000 4.000000], n = 10000000 всего nthreads потоков Интегрирование методом средних прямоугольников (midpoint rule) Состояние гонки данных (data race) const double a = -4.0; const double b = 4.0; const int n = 10000000; Несколько потоков осуществляют конкурентный доступ к разделяемой переменной s – одновременно читают ее и записывают // Глобальная сумма double s = 0.0; double func(double x) { return exp(-x * x); } // s += X Load s -> %reg0 Load X -> %reg1 Add %reg0 %reg1 -> %reg0 Store reg0 -> s void *integrate(void *arg) { struct thread_data *p = (struct thread_data *)arg; double h = (b - a) / n; int points_per_proc = n / p->nthreads; int lb = p->threadno * points_per_proc; int ub = (p->threadno == p->nthreads - 1) ? (n - 1) : (lb + points_per_proc - 1); for (int i = lb; i < ub; i++) s += func(a + h * (i + 0.5)); s *= h; // Обновление глобальной суммы return NULL; } // Вся суть распараллеливания – цикл распределен между потоками lb T0 T0 T0 TID 0 T0 T1 ub T1 T1 TID 1 T1 T2 T2 T2 TID 2 T2 Состояние гонки данных (race condition, data race) Два потока одновременно увеличивают значение переменной x на 1 (начальное значение x = 0) Thread 0 x = x + 1; Thread 1 x = x + 1; Ожидаемый (идеальный) порядок выполнения потоков: первый поток увеличил x, затем второй Time Thread 0 Thread 1 x Значение x = 0 загружается в регистр R процессора 1 Значение 0 в регистре R увеличивается на 1 2 Значение 1 из регистра R записывается в x 1 3 Значение x = 1 загружается в регистр R процессора 1 4 Значение 1 в регистре R увеличивается на 1 1 5 Значение 2 из регистра R записывается в x 2 Ошибки нет Состояние гонки данных (race condition, data race) Два потока одновременно увеличивают значение переменной x на 1 (начальное значение x = 0) Thread 0 x = x + 1; Thread 1 x = x + 1; Реальный порядок выполнения потоков (недетерминированный) (потоки могут выполняться в любой последовательности, приостанавливаться и запускаться) Time Thread 0 Значение x = 0 загружается в регистр R процессора 1 Значение 0 в регистре R увеличивается на 1 Значение x = 0 загружается в регистр R процессора 2 Значение 1 из регистра R записывается в x Значение 1 в регистре R увеличивается на 1 1 Значение 1 из регистра R записывается в x 1 3 Thread 1 x Ошибка - data race (ожидали 2) Состояние гонки данных (data race) ▪ Состояние гонки (race condition, data race) – это состояние программы, в которой несколько потоков одновременно конкурируют за доступ к общей структуре данных (для чтения/записи) ▪ Порядок выполнения потоков заранее не известен – носит случайный характер ▪ Планировщик ОС динамически распределяет процессорное время учитывая текущую загруженность процессорных ядер, нагрузку (потоки, процессы) создают пользователи, поведение которых носит случайных характер ▪ Состояние гонки данных (race condition, data race) трудно обнаруживается в программах и воспроизводится в тестах (Гейзенбаг – heisenbug) Состояние гонки данных (data race) Динамические анализаторы кода ▪ Valgrind Helgrind, DRD ▪ ThreadSanitizer – a data race detector for C/C++ and Go (gcc 4.8, clang) ▪ Intel Thread Checker ▪ Oracle Studio Thread Analyzer ▪ Java ThreadSanitizer ▪ Java Chord Статические анализаторы кода ▪ PVS-Studio (Viva64) Понятие критической секции (critical section) ▪ Критическая секция (critical section) — это участок исполняемого кода, который в любой момент времени выполняется только одним потоком Critical section Thread 0 Wait Thread 1 Thread 2 CS CS Wait Time Мьютексы (mutex) ▪ Мьютекс (mutex) – примитив синхронизации для организации в программах критических секций – взаимного исключения (mutual exclusion) выполнения заданного участка кода в один момент времени более одним потоком double s = 0.0; // разделяемая переменная pthread_mutex_t mutex_sum = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex_sum); s = s + val; pthread_mutex_unlock(&mutex_sum); ▪ lock/acquire – захват мьютекса осуществляется только одним потоком, остальные ожидают его освобождения ▪ unlock/release – освобождение мьютекса Интегрирование методом средних прямоугольников double s = 0.0; pthread_mutex_t mutex_sum = PTHREAD_MUTEX_INITIALIZER; void *integrate(void *arg) { struct thread_data *p = (struct thread_data *)arg; double h = (b - a) / n; int points_per_proc = n / p->nthreads; int lb = p->threadno * points_per_proc; int ub = (p->threadno == p->nthreads - 1) ? (n - 1) : (lb + points_per_proc - 1); double locs = 0.0; for (int i = lb; i < ub; i++) locs += func(a + h * (i + 0.5)); // Update global sum locs *= h; pthread_mutex_lock(&mutex_sum); s += locs; // Критическая секция pthread_mutex_unlock(&mutex_sum); return NULL; } ./integrate Numerical integration (2 threads): [-4.000000, 4.000000], n = 10000000 Result Pi: 3.141589720795 Elapsed time (sec.): 0.151318 $ ./integrate Numerical integration (2 threads): [-4.000000, 4.000000], n = 10000000 Result Pi: 3.141589720795 Elapsed time (sec.): 0.152941 Интегрирование методом средних прямоугольников double s = 0.0; pthread_mutex_t mutex_sum = PTHREAD_MUTEX_INITIALIZER; void *integrate(void *arg) { struct thread_data *p = (struct thread_data *)arg; double h = (b - a) / n; int points_per_proc = n / p->nthreads; int lb = p->threadno * points_per_proc; int ub = (p->threadno == p->nthreads - 1) ? (n - 1) : (lb + points_per_proc - 1); double locs = 0.0; for (int i = lb; i < ub; i++) locs += func(a + h * (i + 0.5)); // Update global sum locs *= h; pthread_mutex_lock(&mutex_sum); s += locs; // Критическая секция pthread_mutex_unlock(&mutex_sum); return NULL; } ./integrate Numerical integration (2 threads): [-4.000000, 4.000000], n = 10000000 Result Pi: 3.141589720795 Elapsed time (sec.): 0.151318 $ ./integrate Numerical integration (2 threads): [-4.000000, 4.000000], n = 10000000 Result Pi: 3.141589720795 Elapsed time (sec.): 0.152941 Информация о системе: процессоры $ cat /proc/cpuinfo processor : 0 cpu family : 6 model : 23 model name : Intel(R) Xeon(R) CPU E5420 @ 2.50GHz stepping : 10 microcode : 0xa0b cpu MHz : 1998.000 cache size : 6144 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 4 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 xsave lahf_lm dtherm tpr_shadow vnmi flexpriority bogomips : 4987.59 clflush size : 64 cache_alignment : 64 address sizes : 38 bits physical, 48 bits virtual Информация о системе: процессоры $ ls /sys/devices/system/cpu drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x -r--r--r-drwxr-xr-x -r--r--r--r--r--r--r--r--r--r--r--r-drwxr-xr-x -r--r--r---w--------w-------rw-r--r-- 9 8 8 8 8 8 8 8 3 2 1 2 1 1 1 1 2 1 1 1 1 root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root root 4096 4096 4096 4096 4096 4096 4096 4096 4096 Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb 9 9 9 9 9 9 9 9 12 12 12 12 12 12 9 9 12 12 12 12 9 13:34 13:34 13:34 13:34 13:34 13:34 13:34 13:34 18:23 18:23 18:23 18:23 18:23 18:23 13:34 18:13 18:23 18:23 18:23 18:23 13:34 cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7 cpufreq cpuidle kernel_max microcode modalias offline online possible power present probe release uevent Информация о системе: процессоры $ dmesg | grep CPU [ 0.000000] [ 0.000000] [ 0.000000] [ 0.000000] [ 0.000000] [ 0.010784] [ 0.010785] [ 0.010788] [ 0.010796] [ 0.033284] stepping: 0a) [ 0.047160] [ 0.180019] [ 3.382722] [ 3.873633] [ 3.873695] [ 3.873747] [ 3.873783] [ 3.873823] [ 3.873865] [ 3.873922] smpboot: Allowing 8 CPUs, 0 hotplug CPUs setup_percpu: NR_CPUS:1024 nr_cpumask_bits:1024 nr_cpu_ids:8 nr_node_ids:1 PERCPU: Embedded 29 pages/cpu @ffff88025fc00000 s86784 r8192 d23808 u262144 SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1 RCU restricting CPUs from NR_CPUS=1024 to nr_cpu_ids=8. CPU: Physical Processor ID: 0 CPU: Processor Core ID: 0 mce: CPU supports 6 MCE banks CPU0: Thermal monitoring enabled (TM2) smpboot: CPU0: Intel(R) Xeon(R) CPU E5420 @ 2.50GHz (fam: 06, model: 17, NMI watchdog: enabled on all Brought up 8 CPUs microcode: CPU0 sig=0x1067a, microcode: CPU1 sig=0x1067a, microcode: CPU2 sig=0x1067a, microcode: CPU3 sig=0x1067a, microcode: CPU4 sig=0x1067a, microcode: CPU5 sig=0x1067a, microcode: CPU6 sig=0x1067a, microcode: CPU7 sig=0x1067a, CPUs, permanently consumes one hw-PMU counter. pf=0x40, pf=0x40, pf=0x40, pf=0x40, pf=0x40, pf=0x40, pf=0x40, pf=0x40, revision=0xa0b revision=0xa0b revision=0xa0b revision=0xa0b revision=0xa0b revision=0xa0b revision=0xa0b revision=0xa0b Ресурсы системы $ lstopo Machine (7980MB) Socket L#0 L2 L#0 (6144KB) L1d L#0 (32KB) + L1i L1d L#1 (32KB) + L1i L2 L#1 (6144KB) L1d L#2 (32KB) + L1i L1d L#3 (32KB) + L1i Socket L#1 L2 L#2 (6144KB) L1d L#4 (32KB) + L1i L1d L#5 (32KB) + L1i L2 L#3 (6144KB) L1d L#6 (32KB) + L1i L1d L#7 (32KB) + L1i HostBridge L#0 PCIBridge PCIBridge PCIBridge PCI 8086:107d Net L#0 "p3p1" PCIBridge PCI 8086:1096 Net L#1 "em1" PCI 8086:1096 Net L#2 "em2" PCIBridge PCI 1002:515e ... L#0 (32KB) + Core L#0 + PU L#0 (P#0) L#1 (32KB) + Core L#1 + PU L#1 (P#4) L#2 (32KB) + Core L#2 + PU L#2 (P#1) L#3 (32KB) + Core L#3 + PU L#3 (P#5) L#4 (32KB) + Core L#4 + PU L#4 (P#2) L#5 (32KB) + Core L#5 + PU L#5 (P#6) L#6 (32KB) + Core L#6 + PU L#6 (P#3) L#7 (32KB) + Core L#7 + PU L#7 (P#7) Ресурсы системы: память $ free total Mem: 16429124 -/+ buffers/cache: Swap: 18108436 used 15327724 2279928 1279484 free 1101400 14149196 16828952 $ cat /sys/devices/system/node/node0/meminfo Node 0 MemTotal: 16429124 kB Node 0 MemFree: 1097292 kB Node 0 MemUsed: 15331832 kB Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Node Active: 7235284 kB Inactive: 7125736 kB Active(anon): 200724 kB Inactive(anon): 1113492 kB Active(file): 7034560 kB Inactive(file): 6012244 kB Unevictable: 0 kB Mlocked: 0 kB Dirty: 252 kB Writeback: 0 kB FilePages: 14127436 kB Mapped: 712380 kB AnonPages: 262700 kB Shmem: 1056 kB KernelStack: 4544 kB PageTables: 58760 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB Slab: 758652 kB SReclaimable: 707824 kB SUnreclaim: 50828 kB AnonHugePages: 34816 kB shared 1056 buffers 361236 cached 12686560 Литература 1. Blaise Barney. POSIX Threads Programming // https://computing.llnl.gov/tutorials/pthreads/ 2. POSIX thread (pthread) libraries // http://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html 3. Эхтер Ш., Робертс Дж. Многоядерное программирование. – СПб.: Питер, 2010. – 316 с. 4. Эндрюс Г.Р. Основы многопоточного, параллельного и распределенного программирования. – М.: Вильямс, 2003. – 512 с. 5. Darryl Gove. Multicore Application Programming: for Windows, Linux, and Oracle Solaris. – Addison-Wesley, 2010. – 480 p. 6. Maurice Herlihy, Nir Shavit. The Art of Multiprocessor Programming. – Morgan Kaufmann, 2008. – 528 p. 7. Richard H. Carver, Kuo-Chung Tai. Modern Multithreading : Implementing, Testing, and Debugging Multithreaded Java and C++/Pthreads/Win32 Programs. – Wiley-Interscience, 2005. – 480 p. 8. Anthony Williams. C++ Concurrency in Action: Practical Multithreading. – Manning Publications, 2012. – 528 p. 9. Träff J.L. Introduction to Parallel Computing // http://www.par.tuwien.ac.at/teach/WS12/ParComp.html
«Многопоточное программирование POSIX Threads» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ
Получи помощь с рефератом от ИИ-шки
ИИ ответит за 2 минуты

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot