From 3019ed2688ef375903255779531a91e2fea333cd Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Sun, 15 Sep 2024 19:50:32 +0200 Subject: [PATCH] Rewrote some microbenchmarks. --- repos/mml/src/app/portal_experiment/main.cc | 76 +++++++++--- repos/mml/src/app/suoritin_test/main.cc | 108 +++++++++++++++++- repos/mml/src/app/thread_test/thread_test.cc | 11 +- .../src/app/volatile_cell/volatile_cell.cc | 21 +++- 4 files changed, 185 insertions(+), 31 deletions(-) diff --git a/repos/mml/src/app/portal_experiment/main.cc b/repos/mml/src/app/portal_experiment/main.cc index 8374a46815..a5562a9759 100644 --- a/repos/mml/src/app/portal_experiment/main.cc +++ b/repos/mml/src/app/portal_experiment/main.cc @@ -12,7 +12,7 @@ #include #define CALLS 100 -#define CORES 4 +#define CORES 14 #define HYPERCALL //Genode::Trace::timestamp(); @@ -26,6 +26,20 @@ static std::atomic ready{false}; static std::atomic restart{true}; static std::atomic yield_ctr{-(31-CORES)}; static unsigned long tsc_freq_khz = 0; +int cores, i; + +struct Channel { + unsigned long yield_flag : 1, + op : 2, + tnum : 61; + unsigned long delta_alloc; + unsigned long delta_activate; + unsigned long delta_setflag; + unsigned long delta_findborrower; + unsigned long delta_block; + unsigned long delta_enter; + unsigned long delta_return; +}; struct Cell : public Genode::Thread { @@ -41,17 +55,19 @@ struct Cell : public Genode::Thread void entry() override { + Genode::Trace::Timestamp latency = 0; Nova::mword_t channel_id = 0; Nova::uint64_t count_allocs = 0; Nova::cpu_id(channel_id); - unsigned long volatile *my_channel = &reinterpret_cast(channel)[channel_id]; + struct Channel *channels = reinterpret_cast(channel); + struct Channel volatile *my_channel = &channels[channel_id]; unsigned long _tsc_freq_ghz = tsc_freq_khz / 1000000UL; - Genode::log("Started worker", _id, " on CPU with affinity ", channel_id, Genode::Thread::myself()->affinity(), " signal channel: ", *my_channel, " at ", my_channel); + //Genode::log("Started worker", _id, " on CPU with affinity ", channel_id, Genode::Thread::myself()->affinity(), " signal channel: ", my_channel->yield_flag, " at ", my_channel); - for (int cores = CORES; cores < 32; cores+=4) { - for (int i = 0; i < CALLS; ) { + for (cores = CORES; cores <= 14; cores+=4) { + for (i = 0; i < CALLS; ) { if ((i == 0 && yield_ctr >= cores-1) || (i > 0 && yield_ctr >= cores-1)) ready = true; @@ -64,18 +80,26 @@ struct Cell : public Genode::Thread //Genode::log("Worker ", _id, " on CPU ", channel_id, " woke up"); counter.fetch_add(1); - if (counter >= cores-1) { - ready = true; - // Genode::log("{\"allocation:\": ", allocation, ", \"id\":", _id, ",\"clk_total\":", (end-::start), ", \"mean_clk\":", (end-::start)/count_allocs ,", \"count\": ", count_allocs, "\"channel-id\":", channel_id, "},"); - } + if (counter >= cores-1) { + ready = true; + // Genode::log("{\"allocation:\": ", allocation, ", \"id\":", _id, ",\"clk_total\":", (end-::start), ", \"mean_clk\":", (end-::start)/count_allocs ,", \"count\": ", count_allocs, "\"channel-id\":", channel_id, "},"); + } + if (my_channel->op == 2) { + Nova::mword_t allocation = 0; + Genode::Trace::Timestamp now = Genode::Trace::timestamp(); + Nova::core_allocation(allocation); + my_channel->delta_return = now - my_channel->delta_return; + Genode::log("{\"iteration\": ", i, ", \"cores\":", cores, ", \"d_block\": ", my_channel->delta_block / _tsc_freq_ghz, ", \"d_enter\":", my_channel->delta_enter / _tsc_freq_ghz, ", \"d_return\":", my_channel->delta_return / _tsc_freq_ghz, ", \"op\": \"yield\"},"); + } + my_channel->op = 0; if (_id == 0) { //Genode::log("Waiting on start signal"); while (ready.load() == false) __builtin_ia32_pause(); //Genode::log("Got start signal"); - _timer.msleep(20); + _timer.msleep(2); //Genode::log("Woke up for new iteration"); ready = false; @@ -90,7 +114,11 @@ struct Cell : public Genode::Thread if (_id == 0) { Nova::mword_t allocated = 0; //Genode::log("Allocating 4 cores"); - + + my_channel->tnum = i; + my_channel->op = 1; /* 1 for alloc, 2 for yield */ + + my_channel->delta_enter = Genode::Trace::timestamp(); Nova::uint8_t rc = Nova::alloc_cores(cores, allocated); if (rc == Nova::NOVA_OK) { @@ -98,13 +126,21 @@ struct Cell : public Genode::Thread while(ready.load() == false) __builtin_ia32_pause(); end = Genode::Trace::timestamp(); + my_channel->delta_return = end - my_channel->delta_return; + latency += (end - ::start) / _tsc_freq_ghz; Nova::mword_t allocation = 0; + Genode::log("{\"iteration\": ", i, ", \"cores\":", cores, ", \"delta_enter:\" ", my_channel->delta_enter / _tsc_freq_ghz, ", \"delta_alloc\": ", my_channel->delta_alloc / _tsc_freq_ghz, ", \"delta_activate:\": ", my_channel->delta_activate / _tsc_freq_ghz, ", \"delta_setflag\": ", my_channel->delta_setflag / _tsc_freq_ghz, ", \"delta_return\": ", my_channel->delta_return / _tsc_freq_ghz, "},"); Nova::core_allocation(allocation); restart = true; - i++; counter = 0; yield_ctr = 0; - Genode::log("{\"cores\":", cores, "\"allocation\": ", allocation, ",\"start\": ", ::start, ", \"end\": ", end, " ,\"us\": ", (end - ::start)/_tsc_freq_ghz,"},"); + //if (i%100==0) { + + Genode::log("{\"iteration\": ", i, ", \"cores\":", cores, ", \"allocation\": ", allocation, ",\"start\": ", ::start, ", \"end\": ", end, " ,\"ns\": ", (latency), "},"); + my_channel->delta_setflag = 0; + latency = 0; + //} + i++; break; } else { //Genode::log("cores allocated: ", allocated); @@ -116,11 +152,10 @@ struct Cell : public Genode::Thread } //Genode::log("Finished allocation. Waiting for yield signal, id = ", channel_id, "\n"); while (restart.load() == false) { - long res = 0; - if ((res = __atomic_load_n(my_channel, __ATOMIC_SEQ_CST)) != 0) - { - Genode::log("Got yield signal on channel ", channel_id, " signal: ", res, " at ", my_channel); - Nova::yield(false); + Channel volatile *res = __atomic_load_n(&my_channel, __ATOMIC_SEQ_CST); + if (res->yield_flag) { + Genode::log("Got yield signal on channel ", channel_id); + Nova::yield(true); } } } @@ -188,6 +223,7 @@ void Libc::Component::construct(Libc::Env &env) pthread_t workers[space.total()]; std::cout << "Creating workers" << std::endl; + Genode::Trace::Timestamp thread_start = Genode::Trace::timestamp(); for (Genode::uint16_t cpu = 1; cpu < space.total(); cpu++) { Genode::String<32> const name{"worker", cpu}; @@ -198,6 +234,8 @@ void Libc::Component::construct(Libc::Env &env) // Genode::log("Created worker for CPU ", cpu); // worker->start(); } + Genode::Trace::Timestamp thread_stop = Genode::Trace::timestamp(); + Genode::log("Took ", (thread_stop - thread_start) / 2000, " μs to start workers"); pthread_t main_pt{}; @@ -209,7 +247,7 @@ void Libc::Component::construct(Libc::Env &env) /*Libc::pthread_create_from_thread(&main_pt, *main, &main); main->start();*/ // Nova::yield(false); - _timer.msleep(150); + //_timer.msleep(10000); Libc::pthread_create_from_session(&main_pt, Cell::pthread_entry, main_cell, 8 * 4096, "main_worker", &env.cpu(), loc); pthread_join(main_pt, 0); }); Genode::log("Leaving component"); diff --git a/repos/mml/src/app/suoritin_test/main.cc b/repos/mml/src/app/suoritin_test/main.cc index 57283b15a0..c080a139ba 100644 --- a/repos/mml/src/app/suoritin_test/main.cc +++ b/repos/mml/src/app/suoritin_test/main.cc @@ -1,20 +1,122 @@ #include +#include #include +#include +#include +#include #include +#include +#include + +#include +#include +class Worker : public Genode::Thread { + + public: + Worker(Genode::Env &env) + : Genode::Thread(env, Name("worker foo"), 4 * 4096) { } + + void entry() override + { + while(true) { + + } + } +}; struct Suoritin_tester { Genode::Env &_env; + Genode::Heap _heap{_env.ram(), _env.rm()}; + Genode::Attached_rom_dataspace _config{_env, "config"}; Suoritin_tester(Genode::Env &env) : _env(env) { - Genode::log("Hello from Suoritin tester"); - Tukija::Suoritin::Connection suoritin {_env}; + bool greedy = false; // Shall this cell always request more resources? default: no + //Genode::log("Hello from Suoritin tester"); + Tukija::Suoritin::Connection suoritin {_env}; + //Genode::log("Created TASKING session"); + + //Genode::log("Reading config"); + _config.update(); + + if (_config.valid()) { + greedy = _config.xml().attribute_value("greedy", false); + } + + /* Create a single dummy worker */ + Worker *foo = new (_heap) Worker(_env); + Worker *bar = new (_heap) Worker(_env); + + //Genode::log("Querying dataspace capabilities for shared mem interface"); + Genode::Dataspace_capability workers_cap = suoritin.worker_if(); + Genode::Dataspace_capability channels_cap = suoritin.channel_if(); + Genode::Dataspace_capability evt_cap = suoritin.event_channel(); + + //Genode::log("Mapping interface into virtual address space"); + Tukija::Suoritin::Worker* workers = env.rm().attach(workers_cap); + Tukija::Suoritin::Channel *channels = env.rm().attach(channels_cap); + //Tukija::Suoritin::Event_channel *evtchn = env.rm().attach(evt_cap); + + //Genode::log("Registering dummy worker named foo"); + suoritin.register_worker(Genode::Thread::Name("foo"), foo->cap()); + + //Genode::log("Creating one dummy task queue aka channel "); + suoritin.create_channel(*workers); + + suoritin.register_worker(Genode::Thread::Name("bar"), bar->cap()); + //Genode::log("Interfaces mapped succesfully"); + //Genode::log("Workers interface: ", workers); + //Genode::log("Channels interface: ", channels); + + //Genode::log("Writing dummy values"); + if (greedy) + channels[0].length(0xDEADBEEF); + else + channels[0].length(0x20); + // //Genode::log("Channel 0 has length ", channels[0].length()); + + suoritin.create_channel(workers[1]); + channels[1].length(0xF00); + + // Genode::log("Waiting for parent to react"); + + Genode::Trace::Timestamp rpc_delay = 0; + + if (greedy) { + Nova::mword_t response = 0; + Genode::Trace::Timestamp start = Genode::Trace::timestamp(); + + for (unsigned long i = 0; i < 2000; i++) { + channels[0].length(0xDEADBEEF); + + // Genode::Trace::Timestamp start = Genode::Trace::timestamp(); + //Nova::hpc_read(0, 1, response); + suoritin.request_cores(); + // Genode::Trace::Timestamp end = Genode::Trace::timestamp(); + // rpc_delay += (end - start); + + /*while (!(__atomic_load_n(&evtchn->parent_flag, __ATOMIC_SEQ_CST))) + __builtin_ia32_pause(); + __atomic_store_n(&evtchn->parent_flag, false, __ATOMIC_SEQ_CST);*/ + } + Genode::Trace::Timestamp end = Genode::Trace::timestamp(); + Genode::log("{\"response\": \"", response, "\", \"delay\": ", (end-start)/4000, ", \"rpc\":", rpc_delay/4000, "},"); + } + + //Genode::log("Exiting"); + while(true) + ; + //_env.parent().exit(0); } }; void Component::construct(Genode::Env &env) { - static Suoritin_tester tester(env); + try { + static Suoritin_tester tester(env); + } catch (Genode::Quota_guard::Limit_exceeded) { + Genode::error("Failed: Caps exceeded."); + } } \ No newline at end of file diff --git a/repos/mml/src/app/thread_test/thread_test.cc b/repos/mml/src/app/thread_test/thread_test.cc index 0b62a708ae..4b9853b3c0 100644 --- a/repos/mml/src/app/thread_test/thread_test.cc +++ b/repos/mml/src/app/thread_test/thread_test.cc @@ -3,9 +3,6 @@ #include #include #include -#include -#include -#include namespace Thread_test { class Tester; @@ -34,12 +31,12 @@ class Thread_test::Test_thread : public Thread { while(true) { Genode::log("Pong from thread ", _id); - auto start = _timer.elapsed_ms(); + auto start = Genode::Trace::timestamp(); // auto start = std::chrono::steady_clock::now (); - _timer.msleep(_id * 1000); - auto end = _timer.elapsed_ms(); + _timer.usleep(_id * 10); + auto end = Genode::Trace::timestamp(); // auto end = std::chrono::steady_clock::now(); - Genode::log("Thread ", _id, " woke up afer", (end-start), " ms."); + Genode::log("Thread ", _id, " woke up afer", (end-start)/2000, " us."); Genode::log("My affinities are ", this->affinity().xpos(), "x", this->affinity().ypos(), " node: ", _env.topo().node_affinity_of(this->affinity()).id(), " native region: ", _env.topo().node_affinity_of(this->affinity()).native_id()); } } diff --git a/repos/mml/src/app/volatile_cell/volatile_cell.cc b/repos/mml/src/app/volatile_cell/volatile_cell.cc index bf5c8f7c1f..cc5599b6f0 100644 --- a/repos/mml/src/app/volatile_cell/volatile_cell.cc +++ b/repos/mml/src/app/volatile_cell/volatile_cell.cc @@ -33,6 +33,20 @@ void short_loop(unsigned long k) } } +struct Channel { + unsigned long yield_flag : 1, + op : 2, + tnum : 61; + unsigned long delta_alloc; + unsigned long delta_activate; + unsigned long delta_setflag; + unsigned long delta_findborrower; + unsigned long delta_block; + unsigned long delta_enter; + unsigned long delta_return; +}; + + struct Hoitaja_test::Worker : public Genode::Thread { Genode::uint16_t _id; @@ -41,14 +55,17 @@ struct Hoitaja_test::Worker : public Genode::Thread { Nova::mword_t channel_id = 0; Nova::cpu_id(channel_id); - unsigned long volatile *my_channel = &reinterpret_cast(channel)[channel_id]; + //unsigned long volatile *my_channel = &reinterpret_cast(channel)[channel_id]; + Channel *channels = reinterpret_cast(channel); + Channel *my_channel_struct = &channels[channel_id]; //Genode::log("Started worker ", _id, " on CPU ", channel_id); Nova::yield(); while (true) { - while (!(__atomic_load_n(my_channel, __ATOMIC_SEQ_CST))) + while (!(my_channel_struct->yield_flag)) short_loop(770); //Genode::log("Returning core ", channel_id); + my_channel_struct->delta_enter = Genode::Trace::timestamp(); Nova::yield(false); } }