-
Notifications
You must be signed in to change notification settings - Fork 256
Description
While auditing the generated C++ source code for Network.cpp, I noticed a logic flaw in the main execution loop that causes massive overhead when reporting is enabled.
Currently, the Network::run loop iterates over all objects (objects.size()). Inside this inner loop, if a report_func is active, the code calls std::chrono::high_resolution_clock::now() for every single object at every time step.
The generated code looks like this:
// Inside the main timestep loop
for(size_t i=0; i<objects.size(); i++)
{
// ... object update logic ...
if (report_func)
{
// THIS IS THE ISSUE:
// We are hitting the system clock N times per timestep (where N = objects)
current = std::chrono::high_resolution_clock::now();
const double elapsed = std::chrono::duration<double>(current - start).count();
if (elapsed > next_report_time) {
// ... report logic
}
}
}Impact
Since std::chrono::...::now() often triggers a system call, this gets expensive fast.
For a network with just 50 objects (NeuronGroups, Synapses, Monitors, etc.) running for 10^6 steps, we are triggering 50 million system calls.
This artificially inflates the runtime, particularly for lightweight simulations where the computation per step is small compared to the syscall latency. The clock should really only be sampled once per global time step, not per object.