Skip to content

Commit d33383f

Browse files
committed
perf: use concurrent instead of coroutine
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
1 parent 4c3f232 commit d33383f

2 files changed

Lines changed: 72 additions & 138 deletions

File tree

t4_devkit/helper/rendering.py

Lines changed: 69 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

3-
import asyncio
3+
import concurrent
4+
import concurrent.futures
45
import os.path as osp
56
from concurrent.futures import Future
67
from typing import TYPE_CHECKING, Sequence
@@ -49,14 +50,16 @@ def __init__(self, t4: Tier4) -> None:
4950
category.name: idx for idx, category in enumerate(self._t4.category)
5051
}
5152

52-
async def async_render_scene(
53+
self._executor = concurrent.futures.ThreadPoolExecutor()
54+
55+
def render_scene(
5356
self,
5457
scene_token: str,
5558
*,
5659
max_time_seconds: float = np.inf,
5760
future_seconds: float = 0.0,
5861
save_dir: str | None = None,
59-
) -> Future:
62+
) -> None:
6063
"""Render specified scene.
6164
6265
Args:
@@ -65,9 +68,6 @@ async def async_render_scene(
6568
future_seconds (float, optional): Future time in [s].
6669
save_dir (str | None, optional): Directory path to save the recording.
6770
Viewer will be spawned if it is None, otherwise not.
68-
69-
Returns:
70-
Future aggregating results.
7171
"""
7272
# search first sample data tokens
7373
first_lidar_tokens: list[str] = []
@@ -98,44 +98,43 @@ async def async_render_scene(
9898
first_sample: Sample = self._t4.get("sample", scene.first_sample_token)
9999
max_timestamp_us = first_sample.timestamp + sec2us(max_time_seconds)
100100

101-
gather = await asyncio.gather(
101+
concurrent.futures.wait(
102102
self._render_lidar_and_ego(
103103
viewer=viewer,
104104
first_lidar_tokens=first_lidar_tokens,
105105
max_timestamp_us=max_timestamp_us,
106-
),
107-
self._render_radars(
106+
)
107+
+ self._render_radars(
108108
viewer=viewer,
109109
first_radar_tokens=first_radar_tokens,
110110
max_timestamp_us=max_timestamp_us,
111-
),
112-
self._render_cameras(
111+
)
112+
+ self._render_cameras(
113113
viewer=viewer,
114114
first_camera_tokens=first_camera_tokens,
115115
max_timestamp_us=max_timestamp_us,
116116
),
117-
self._render_annotation3ds(
118-
viewer=viewer,
119-
first_sample_token=scene.first_sample_token,
120-
max_timestamp_us=max_timestamp_us,
121-
future_seconds=future_seconds,
122-
),
123-
self._render_annotation2ds(
124-
viewer=viewer,
125-
first_sample_token=scene.first_sample_token,
126-
max_timestamp_us=max_time_seconds,
127-
),
128117
)
129118

130-
return gather
119+
self._render_annotation3ds(
120+
viewer=viewer,
121+
first_sample_token=scene.first_sample_token,
122+
max_timestamp_us=max_timestamp_us,
123+
future_seconds=future_seconds,
124+
)
125+
self._render_annotation2ds(
126+
viewer=viewer,
127+
first_sample_token=scene.first_sample_token,
128+
max_timestamp_us=max_time_seconds,
129+
)
131130

132-
async def async_render_instance(
131+
def render_instance(
133132
self,
134133
instance_token: str | Sequence[str],
135134
*,
136135
future_seconds: float = 0.0,
137136
save_dir: str | None = None,
138-
) -> Future:
137+
) -> None:
139138
"""Render particular instance.
140139
141140
Args:
@@ -144,8 +143,6 @@ async def async_render_instance(
144143
save_dir (str | None, optional): Directory path to save the recording.
145144
Viewer will be spawned if it is None, otherwise not.
146145
147-
Returns:
148-
Future aggregating results.
149146
"""
150147
instance_tokens = [instance_token] if isinstance(instance_token, str) else instance_token
151148

@@ -195,47 +192,46 @@ async def async_render_instance(
195192
save_dir=save_dir,
196193
)
197194

198-
gather = await asyncio.gather(
195+
concurrent.futures.wait(
199196
self._render_lidar_and_ego(
200197
viewer=viewer,
201198
first_lidar_tokens=first_lidar_tokens,
202199
max_timestamp_us=max_timestamp_us,
203-
),
204-
self._render_radars(
200+
)
201+
+ self._render_radars(
205202
viewer=viewer,
206203
first_radar_tokens=first_radar_tokens,
207204
max_timestamp_us=max_timestamp_us,
208-
),
209-
self._render_cameras(
205+
)
206+
+ self._render_cameras(
210207
viewer=viewer,
211208
first_camera_tokens=first_camera_tokens,
212209
max_timestamp_us=max_timestamp_us,
213210
),
214-
self._render_annotation3ds(
215-
viewer=viewer,
216-
first_sample_token=first_sample.token,
217-
max_timestamp_us=max_timestamp_us,
218-
future_seconds=future_seconds,
219-
instance_tokens=instance_tokens,
220-
),
221-
self._render_annotation2ds(
222-
viewer=viewer,
223-
first_sample_token=first_sample.token,
224-
max_timestamp_us=max_timestamp_us,
225-
instance_tokens=instance_tokens,
226-
),
227211
)
228212

229-
return gather
213+
self._render_annotation3ds(
214+
viewer=viewer,
215+
first_sample_token=first_sample.token,
216+
max_timestamp_us=max_timestamp_us,
217+
future_seconds=future_seconds,
218+
instance_tokens=instance_tokens,
219+
)
220+
self._render_annotation2ds(
221+
viewer=viewer,
222+
first_sample_token=first_sample.token,
223+
max_timestamp_us=max_timestamp_us,
224+
instance_tokens=instance_tokens,
225+
)
230226

231-
async def async_render_pointcloud(
227+
def render_pointcloud(
232228
self,
233229
scene_token: str,
234230
*,
235231
max_time_seconds: float = np.inf,
236232
ignore_distortion: bool = True,
237233
save_dir: str | None = None,
238-
) -> Future:
234+
) -> None:
239235
"""Render pointcloud on 3D and 2D view.
240236
241237
Args:
@@ -245,9 +241,6 @@ async def async_render_pointcloud(
245241
save_dir (str | None, optional): Directory path to save the recording.
246242
Viewer will be spawned if it is None, otherwise not.
247243
248-
Returns:
249-
Future aggregating results.
250-
251244
TODO:
252245
Add an option of rendering radar channels.
253246
"""
@@ -268,22 +261,20 @@ async def async_render_pointcloud(
268261
first_lidar_sample_data: Sample = self._t4.get("sample_data", first_lidar_token)
269262
max_timestamp_us = first_lidar_sample_data.timestamp + sec2us(max_time_seconds)
270263

271-
gather = await asyncio.gather(
264+
concurrent.futures.wait(
272265
self._render_lidar_and_ego(
273266
viewer=viewer,
274267
first_lidar_tokens=[first_lidar_token],
275268
max_timestamp_us=max_timestamp_us,
276-
),
277-
self._render_points_on_cameras(
269+
)
270+
+ self._render_points_on_cameras(
278271
first_point_sample_data_token=first_lidar_token,
279272
max_timestamp_us=max_timestamp_us,
280273
min_dist=1.0,
281274
ignore_distortion=ignore_distortion,
282275
),
283276
)
284277

285-
return gather
286-
287278
def _init_viewer(
288279
self,
289280
app_id: str,
@@ -335,17 +326,13 @@ def _render_sensor_calibration(self, viewer: RerunViewer, sample_data_token: str
335326
sensor: Sensor = self._t4.get("sensor", calibration.sensor_token)
336327
viewer.render_calibration(sensor=sensor, calibration=calibration)
337328

338-
async def _render_lidar_and_ego(
329+
def _render_lidar_and_ego(
339330
self,
340331
viewer: RerunViewer,
341332
first_lidar_tokens: list[str],
342333
max_timestamp_us: float,
343-
) -> Future:
344-
async def render_lidar(
345-
viewer: RerunViewer,
346-
first_lidar_token: str,
347-
max_timestamp_us: float,
348-
) -> None:
334+
) -> list[Future]:
335+
def _render_single_lidar(first_lidar_token: str) -> None:
349336
self._render_sensor_calibration(viewer=viewer, sample_data_token=first_lidar_token)
350337

351338
current_lidar_token = first_lidar_token
@@ -369,28 +356,15 @@ async def render_lidar(
369356

370357
current_lidar_token = sample_data.next
371358

372-
return await asyncio.gather(
373-
*[
374-
render_lidar(
375-
viewer=viewer,
376-
first_lidar_token=token,
377-
max_timestamp_us=max_timestamp_us,
378-
)
379-
for token in first_lidar_tokens
380-
]
381-
)
359+
return [self._executor.submit(_render_single_lidar, token) for token in first_lidar_tokens]
382360

383-
async def _render_radars(
361+
def _render_radars(
384362
self,
385363
viewer: RerunViewer,
386364
first_radar_tokens: list[str],
387365
max_timestamp_us: float,
388-
) -> Future:
389-
async def render_radar(
390-
viewer: RerunViewer,
391-
first_radar_token: str,
392-
max_timestamp_us: float,
393-
) -> None:
366+
) -> list[Future]:
367+
def _render_single_radar(first_radar_token: str) -> None:
394368
self._render_sensor_calibration(viewer=viewer, sample_data_token=first_radar_token)
395369

396370
current_radar_token = first_radar_token
@@ -411,28 +385,15 @@ async def render_radar(
411385

412386
current_radar_token = sample_data.next
413387

414-
return await asyncio.gather(
415-
*[
416-
render_radar(
417-
viewer=viewer,
418-
first_radar_token=token,
419-
max_timestamp_us=max_timestamp_us,
420-
)
421-
for token in first_radar_tokens
422-
]
423-
)
388+
return [self._executor.submit(_render_single_radar, token) for token in first_radar_tokens]
424389

425-
async def _render_cameras(
390+
def _render_cameras(
426391
self,
427392
viewer: RerunViewer,
428393
first_camera_tokens: list[str],
429394
max_timestamp_us: float,
430395
) -> Future:
431-
async def render_camera(
432-
viewer: RerunViewer,
433-
first_camera_token: str,
434-
max_timestamp_us: float,
435-
) -> None:
396+
def _render_single_camera(first_camera_token: str) -> None:
436397
self._render_sensor_calibration(viewer=viewer, sample_data_token=first_camera_token)
437398

438399
current_camera_token = first_camera_token
@@ -450,32 +411,19 @@ async def render_camera(
450411

451412
current_camera_token = sample_data.next
452413

453-
return await asyncio.gather(
454-
*[
455-
render_camera(
456-
viewer=viewer,
457-
first_camera_token=token,
458-
max_timestamp_us=max_timestamp_us,
459-
)
460-
for token in first_camera_tokens
461-
]
462-
)
414+
return [
415+
self._executor.submit(_render_single_camera, token) for token in first_camera_tokens
416+
]
463417

464-
async def _render_points_on_cameras(
418+
def _render_points_on_cameras(
465419
self,
466420
first_point_sample_data_token: str,
467421
max_timestamp_us: float,
468422
*,
469423
min_dist: float = 1.0,
470424
ignore_distortion: bool = True,
471425
) -> Future:
472-
async def render_points_on_camera(
473-
first_point_sample_data_token: str,
474-
camera: str,
475-
*,
476-
min_dist: float = 1.0,
477-
ignore_distortion: bool = True,
478-
) -> None:
426+
def _render_points_on_single_camera(camera: str) -> None:
479427
current_point_sample_data_token = first_point_sample_data_token
480428
while current_point_sample_data_token != "":
481429
sample_data: SampleData = self._t4.get(
@@ -509,18 +457,11 @@ async def render_points_on_camera(
509457

510458
current_point_sample_data_token = sample_data.next
511459

512-
return await asyncio.gather(
513-
*[
514-
render_points_on_camera(
515-
first_point_sample_data_token=first_point_sample_data_token,
516-
camera=sensor.channel,
517-
min_dist=min_dist,
518-
ignore_distortion=ignore_distortion,
519-
)
520-
for sensor in self._t4.sensor
521-
if sensor.modality == SensorModality.CAMERA
522-
]
523-
)
460+
return [
461+
self._executor.submit(_render_points_on_single_camera, sensor.channel)
462+
for sensor in self._t4.sensor
463+
if sensor.modality == SensorModality.CAMERA
464+
]
524465

525466
def _project_pointcloud(
526467
self,
@@ -602,7 +543,7 @@ def _project_pointcloud(
602543

603544
return points_on_img, depths, np.array(img, dtype=np.uint8)
604545

605-
async def _render_annotation3ds(
546+
def _render_annotation3ds(
606547
self,
607548
viewer: RerunViewer,
608549
first_sample_token: str,
@@ -633,7 +574,7 @@ async def _render_annotation3ds(
633574

634575
current_sample_token = sample.next
635576

636-
async def _render_annotation2ds(
577+
def _render_annotation2ds(
637578
self,
638579
viewer: RerunViewer,
639580
first_sample_token: str,

0 commit comments

Comments
 (0)