courses:high_performance_computing:producer_consumer
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
courses:high_performance_computing:producer_consumer [2019/09/09 16:44] – odoronin | courses:high_performance_computing:producer_consumer [2025/02/23 14:55] (current) – odoronin | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== |
+ | > [[https:// | ||
Ваша задача - реализовать классический паттерн producer-consumer с небольшими дополнительными условиями. | Ваша задача - реализовать классический паттерн producer-consumer с небольшими дополнительными условиями. | ||
Программа должна состоять из 3+N потоков: | Программа должна состоять из 3+N потоков: | ||
- | - главный | + | - Главный |
- producer | - producer | ||
- interruptor | - interruptor | ||
- N потоков consumer | - N потоков consumer | ||
- | На стандартный ввод программе подается | + | В файл, чтение которого уже |
* Задача producer-потока - получить на вход список чисел, и по очереди использовать каждое значение из этого списка для обновления переменной разделяемой между потоками | * Задача producer-потока - получить на вход список чисел, и по очереди использовать каждое значение из этого списка для обновления переменной разделяемой между потоками | ||
* Задача consumer-потоков отреагировать на уведомление от producer и набирать сумму полученных значений. Также этот поток должен защититься от попыток потока-interruptor его остановить. Дополнительные условия: | * Задача consumer-потоков отреагировать на уведомление от producer и набирать сумму полученных значений. Также этот поток должен защититься от попыток потока-interruptor его остановить. Дополнительные условия: | ||
Line 13: | Line 15: | ||
- Потоки consumer не должны дублировать вычисления друг с другом одних и тех же значений | - Потоки consumer не должны дублировать вычисления друг с другом одних и тех же значений | ||
- В качестве возвращаемого значения поток должен вернуть свою частичную посчитанную сумму | - В качестве возвращаемого значения поток должен вернуть свою частичную посчитанную сумму | ||
- | * Задача потока-interruptor проста: | + | * Задача потока-interruptor проста: |
- | + | * Завершение приложения происходит или при считывании перевода каретки из файла или по посылке сигнала SIGTERM, обработку которого нужно также добавить. В обработчике сигнала можно вызывать только signal-safe функции https:// | |
- | Функция run_threads должна запускать все потоки, | + | * При сигнале в качестве вывода нужно выдавать посчитанную на этот момент сумму |
+ | * В нашем producer/ | ||
+ | Функция run_threads должна запускать все потоки, | ||
+ | * При отсутствии входных данных ядра процессора не должны вхолостую есть такты | ||
Для обеспечения межпоточного взаимодействия допускается использование только pthread API. На вход приложения передаётся 2 аргумента при старте именно в такой последовательности: | Для обеспечения межпоточного взаимодействия допускается использование только pthread API. На вход приложения передаётся 2 аргумента при старте именно в такой последовательности: | ||
- Число потоков consumer | - Число потоков consumer | ||
- Верхний предел сна consumer в миллисекундах | - Верхний предел сна consumer в миллисекундах | ||
- | |||
- | |||
- | Так-же необходимо реализовать поддержку ключа --debug, при использовании которого каждый consumer-поток будет выводить пару (tid, psum), где tid реализуется с помощью функции get_tid(), а psum это сумма которую посчитал поток. Вывод значений psum происходит при каждом изменении. | ||
- | |||
- | Функция get_tid() возвращает идентификатор потока. Идентификатор потока это не проста pthread_self(), | ||
В поток вывода должно попадать только результирующее значение, | В поток вывода должно попадать только результирующее значение, | ||
+ | В случае детектирования ошибок нужно выдавать не нулевой код возврата. | ||
<file cpp> | <file cpp> | ||
+ | #include < | ||
+ | #include < | ||
#include < | #include < | ||
void* producer_routine(void* arg) { | void* producer_routine(void* arg) { | ||
- | // Wait for consumer to start | + | // Wait for consumer to start. |
+ | // You should use this waiting only for debugging your code | ||
+ | // For the final solution please remove this waiting | ||
// Read data, loop through each value and update the value, notify consumer, wait for consumer to process | // Read data, loop through each value and update the value, notify consumer, wait for consumer to process | ||
+ | std:: | ||
+ | // ... | ||
} | } | ||
void* consumer_routine(void* arg) { | void* consumer_routine(void* arg) { | ||
// notify about start | // notify about start | ||
+ | // you should use this notification only for debugging your code | ||
+ | // for the final solution please remove this notification | ||
+ | | ||
+ | | ||
// for every update issued by producer, read the value and add to sum | // for every update issued by producer, read the value and add to sum | ||
// return pointer to result (for particular consumer) | // return pointer to result (for particular consumer) | ||
Line 45: | Line 56: | ||
void* consumer_interruptor_routine(void* arg) { | void* consumer_interruptor_routine(void* arg) { | ||
// wait for consumers to start | // wait for consumers to start | ||
+ | // you should use this waiting only for debugging your code | ||
+ | // for the final solution please remove this waiting | ||
// interrupt random consumer while producer is running | // interrupt random consumer while producer is running | ||
Line 53: | Line 66: | ||
// return aggregated sum of values | // return aggregated sum of values | ||
- | return 0; | ||
- | } | ||
- | |||
- | int get_tid() { | ||
- | // 1 to 3+N thread ID | ||
- | | ||
return 0; | return 0; | ||
} | } |
courses/high_performance_computing/producer_consumer.1568036683.txt.gz · Last modified: 2019/09/09 16:44 by odoronin