Skip to content

Commit 0aacbf2

Browse files
committed
Refactor: optimize Network.run using function dispatching
1 parent 4960df7 commit 0aacbf2

1 file changed

Lines changed: 69 additions & 48 deletions

File tree

brian2/core/network.py

Lines changed: 69 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,68 +1186,89 @@ def run(
11861186
clock, curclocks = self._nextclocks()
11871187
timestep, t = self._clock_variables[clock]
11881188

1189-
running = timestep[0] < clock._i_end
1190-
11911189
active_objects = [obj for obj in all_objects if obj.active]
11921190

1193-
Network._globally_running = True
1194-
while running and not self._stopped and not Network._globally_stopped:
1195-
if not single_clock:
1196-
timestep, t = self._clock_variables[clock]
1197-
# update the network time to this clock's time
1198-
self.t_ = t[0]
1199-
if report is not None:
1200-
current = time.time()
1201-
if current > next_report_time:
1202-
report_callback(
1203-
(current - start_time) * second,
1204-
(self.t_ - float(t_start)) / float(t_end - t_start),
1205-
t_start,
1206-
duration,
1207-
)
1208-
next_report_time = current + report_period
1191+
if single_clock:
1192+
clock = list(self._clocks)[0]
1193+
advance = clock.advance
1194+
timestep_arr = clock.variables["timestep"].get_value()
1195+
t_arr = clock.variables["t"].get_value()
1196+
i_end = clock._i_end
12091197

1210-
# update the objects and tick forward the clock(s)
1211-
if single_clock:
1212-
if profile:
1213-
for obj in active_objects:
1214-
obj_time = time.time()
1215-
obj.run()
1216-
profiling_info[obj.name] += time.time() - obj_time
1217-
else:
1198+
if profile:
1199+
1200+
def update():
12181201
for obj in active_objects:
1202+
obj_start = time.time()
12191203
obj.run()
1220-
1221-
clock.advance()
1204+
profiling_info[obj.name] += time.time() - obj_start
12221205

12231206
else:
1224-
if profile:
1207+
# Cache bound methods to avoid attribute lookup overhead in the hot loop
1208+
objects_run = [obj.run for obj in active_objects]
1209+
1210+
def update():
1211+
for f in objects_run:
1212+
f()
1213+
1214+
else:
1215+
1216+
def advance():
1217+
for c in curclocks:
1218+
c.advance()
1219+
1220+
if profile:
1221+
1222+
def update():
12251223
for obj in active_objects:
12261224
if obj._clock in curclocks:
1227-
obj_time = time.time()
1225+
obj_start = time.time()
12281226
obj.run()
1229-
profiling_info[obj.name] += time.time() - obj_time
1230-
else:
1227+
profiling_info[obj.name] += time.time() - obj_start
1228+
1229+
else:
1230+
1231+
def update():
12311232
for obj in active_objects:
12321233
if obj._clock in curclocks:
12331234
obj.run()
12341235

1235-
for c in curclocks:
1236-
c.advance()
1237-
# find the next clocks to be updated. The < operator for Clock
1238-
# determines that the first clock to be updated should be the one
1239-
# with the smallest t value, unless there are several with the
1240-
# same t value in which case we update all of them
1241-
clock, curclocks = self._nextclocks()
1242-
timestep, t = self._clock_variables[clock]
1243-
1244-
if (
1245-
device._maximum_run_time is not None
1246-
and time.time() - start_time > float(device._maximum_run_time)
1247-
):
1248-
self._stopped = True
1249-
else:
1250-
running = timestep[0] < clock._i_end
1236+
Network._globally_running = True
1237+
try:
1238+
while not self._stopped and not Network._globally_stopped:
1239+
if not single_clock:
1240+
clock, curclocks = self._nextclocks()
1241+
timestep_arr = clock.variables["timestep"].get_value()
1242+
t_arr = clock.variables["t"].get_value()
1243+
i_end = clock._i_end
1244+
1245+
if timestep_arr[0] >= i_end:
1246+
break
1247+
1248+
self.t_ = t_arr[0]
1249+
1250+
if report is not None:
1251+
current = time.time()
1252+
if current > next_report_time:
1253+
report_callback(
1254+
(current - start_time) * second,
1255+
(self.t_ - float(t_start)) / float(t_end - t_start),
1256+
t_start,
1257+
duration,
1258+
)
1259+
next_report_time = current + report_period
1260+
1261+
update()
1262+
1263+
advance()
1264+
1265+
if (
1266+
device._maximum_run_time is not None
1267+
and time.time() - start_time > float(device._maximum_run_time)
1268+
):
1269+
self._stopped = True
1270+
finally:
1271+
Network._globally_running = False
12511272

12521273
end_time = time.time()
12531274
Network._globally_running = False

0 commit comments

Comments
 (0)