Olej писал(а): ↑25 фев 2021, 23:11
(корутины coroutines, которые могут быть ещё выиграшнее я просто ещё не успел сделать, времени нет)
А вот и оно ... это наш 3-й компонент в сравнении.
Здесь код будет самый простой по форме и лаконичный ... но самый сложный для понимания
Код: Выделить всё
#include <boost/coroutine/all.hpp>
#include <vector>
#include "common.h"
typedef boost::coroutines::symmetric_coroutine<int> coro_t; // параметр int
std::vector<coro_t::call_type*> vpcoro;
void worker(coro_t::yield_type& yield){
for(int n = 0; n < ::nserv; n++ )
{
int val = yield.get(), // извлечь номер следующего
next = (val + 1) % vpcoro.size(); // и кому ему передать управление
if (debug_level > 1)
std::cerr << "coroutine: " << vpcoro[val] << " id: " << val << "->" << next
<< " loop=" << n << std::endl;
delay(ones);
yield(*vpcoro[val], next); // передать следующему
}
}
int main( int argc, char * argv[])
{
opts(argc, argv); // опции командной строки
auto begin = std::chrono::steady_clock::now();
for (int i = 0; i < nwork; i++)
vpcoro.push_back(new coro_t::call_type(worker));
(*vpcoro[0])(1); // старт 1-й корутины
auto end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
std::cout << "полное время (мксек.) = " << elapsed.count() / 1000 << "."
<< elapsed.count() % 1000 << std::endl;
}
- корутине, с типом параметра int, передаётся в качестве этого int - номер корутины (в векторе их таких vpcoro) которой управление нужно передать следующей (выполнив свою работу) - это значение val в функции корутины;
- она же вычисляет "подсказку" для корутины val какой номер той отдавать управление далее - next.
Код: Выделить всё
olej@nvidia:~/2021_WORK/OWN_TEST.codes/coroutine$ make
g++ -Wall -pedantic -std=c++17 coroutS.cc -o coroutS -lboost_coroutine -lboost_context
С отладочной диагностикой это выглядит так:
Код: Выделить всё
olej@nvidia:~/2021_WORK/OWN_TEST.codes/coroutine$ ./coroutS -vv
3 активностей : 5 циклов по 1000 повторов в цикле
coroutine: 0x55b25c534550 id: 1->2 loop=0
coroutine: 0x55b25c534530 id: 2->0 loop=0
coroutine: 0x55b25c524500 id: 0->1 loop=0
coroutine: 0x55b25c534550 id: 1->2 loop=1
coroutine: 0x55b25c534530 id: 2->0 loop=1
coroutine: 0x55b25c524500 id: 0->1 loop=1
coroutine: 0x55b25c534550 id: 1->2 loop=2
coroutine: 0x55b25c534530 id: 2->0 loop=2
coroutine: 0x55b25c524500 id: 0->1 loop=2
coroutine: 0x55b25c534550 id: 1->2 loop=3
coroutine: 0x55b25c534530 id: 2->0 loop=3
coroutine: 0x55b25c524500 id: 0->1 loop=3
coroutine: 0x55b25c534550 id: 1->2 loop=4
coroutine: 0x55b25c534530 id: 2->0 loop=4
coroutine: 0x55b25c524500 id: 0->1 loop=4
полное время (мксек.) = 370.78
А сравнительные времена выполнения:
Код: Выделить всё
olej@nvidia:~/2021_WORK/OWN_TEST.codes/coroutine$ ./threadS -a50 -r30 -d200
полное время (мксек.) = 1926346.606
Код: Выделить всё
olej@nvidia:~/2021_WORK/OWN_TEST.codes/coroutine$ ./fiberS -a50 -r30 -d200
полное время (мксек.) = 226150.404
Код: Выделить всё
olej@nvidia:~/2021_WORK/OWN_TEST.codes/coroutine$ ./coroutS -a50 -r30 -d200
полное время (мксек.) = 228704.229
При коротких задержках на активностях (малые значения -d), т.е. частых переключениях между ветвями, как следовало ожидать, корутины практически
на порядок быстрее справляются, чем вытесняющая многозадачность управляемая ядром системы.
P.S. В приложенных файлах common.h и предыдущие 2 варианта - это только повторы того что было (возможно есть минимальные изменения, но это только для единообразия), а вот новое здесь, понятно - coroutS.cc