Skip to content

Commit a4336c2

Browse files
authored
Update example code (#858)
1 parent ba5ca89 commit a4336c2

2 files changed

Lines changed: 31 additions & 36 deletions

File tree

examples/image_dataloading.py

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@
3030
--num-workers 8 # The number of GPUs
3131
"""
3232

33-
# pyre-ignore-all-errors
33+
# pyre-strict
3434

35+
import argparse
3536
import logging
3637
import signal
3738
import time
39+
from argparse import Namespace
3840
from collections.abc import Iterator
3941
from dataclasses import dataclass
42+
from functools import partial
4043
from pathlib import Path
4144
from threading import Event
4245

@@ -47,7 +50,7 @@
4750
from spdl.pipeline import Pipeline, PipelineBuilder
4851
from torch import Tensor
4952

50-
_LG = logging.getLogger(__name__)
53+
_LG: logging.Logger = logging.getLogger(__name__)
5154

5255
__all__ = [
5356
"entrypoint",
@@ -60,27 +63,25 @@
6063
]
6164

6265

63-
def _parse_args(args):
64-
import argparse
65-
66+
def _parse_args(args: list[str]) -> Namespace:
6667
parser = argparse.ArgumentParser(
6768
description=__doc__,
6869
formatter_class=argparse.RawDescriptionHelpFormatter,
6970
)
7071
parser.add_argument("--debug", action="store_true")
7172
parser.add_argument("--input-flist", type=Path, required=True)
7273
parser.add_argument("--max-samples", type=int)
73-
parser.add_argument("--prefix")
74+
parser.add_argument("--prefix", required=True)
7475
parser.add_argument("--batch-size", type=int, default=32)
7576
parser.add_argument("--trace", type=Path)
7677
parser.add_argument("--buffer-size", type=int, default=16)
7778
parser.add_argument("--num-threads", type=int, default=16)
7879
parser.add_argument("--worker-id", type=int, required=True)
7980
parser.add_argument("--num-workers", type=int, required=True)
80-
args = parser.parse_args(args)
81-
if args.trace:
82-
args.max_samples = args.batch_size * 40
83-
return args
81+
ns = parser.parse_args(args)
82+
if ns.trace:
83+
ns.max_samples = ns.batch_size * 40
84+
return ns
8485

8586

8687
def source(
@@ -108,11 +109,11 @@ def source(
108109
yield prefix + line
109110

110111

111-
async def batch_decode(
112+
def batch_decode(
112113
srcs: list[str],
114+
device_config: spdl.io.CUDAConfig,
113115
width: int = 224,
114116
height: int = 224,
115-
device_config: spdl.io.CUDAConfig | None = None,
116117
) -> Tensor:
117118
"""Given image paths, decode, resize, batch and optionally send them to GPU.
118119
@@ -124,7 +125,7 @@ async def batch_decode(
124125
Returns:
125126
The batch tensor.
126127
"""
127-
buffer = await spdl.io.async_load_image_batch(
128+
buffer = spdl.io.load_image_batch(
128129
srcs,
129130
width=width,
130131
height=height,
@@ -158,29 +159,25 @@ def get_pipeline(
158159
Returns:
159160
The pipeline that performs batch image decoding and device transfer.
160161
"""
161-
162-
async def _batch_decode(srcs):
163-
return await batch_decode(srcs, device_config=device_config)
162+
decode = partial(batch_decode, device_config=device_config)
164163

165164
pipeline = (
166165
PipelineBuilder()
167166
.add_source(src)
168167
.aggregate(batch_size)
169-
.pipe(_batch_decode, concurrency=num_threads, report_stats_interval=15)
168+
.pipe(decode, concurrency=num_threads)
170169
.add_sink(buffer_size)
171-
.build(num_threads=num_threads)
170+
.build(num_threads=num_threads, report_stats_interval=15)
172171
)
173172
return pipeline
174173

175174

176-
def _get_pipeline(args):
175+
def _get_pipeline(args: Namespace) -> Pipeline:
177176
return get_pipeline(
178177
source(args.input_flist, args.prefix, args.num_workers, args.worker_id),
179178
args.batch_size,
180179
device_config=(
181-
None
182-
if args.worker_id is None
183-
else spdl.io.cuda_config(
180+
spdl.io.cuda_config(
184181
device_index=args.worker_id,
185182
allocator=(
186183
torch.cuda.caching_allocator_alloc,
@@ -207,13 +204,13 @@ class PerfResult:
207204
"""The number of frames processed."""
208205

209206

210-
def worker_entrypoint(args: list[str]) -> PerfResult:
207+
def worker_entrypoint(args_: list[str]) -> PerfResult:
211208
"""Entrypoint for worker process. Load images to a GPU and measure its performance.
212209
213210
It builds a :py:class:`~spdl.pipeline.Pipeline` object using :py:func:`get_pipeline`
214211
function and run it with :py:func:`benchmark` function.
215212
"""
216-
args = _parse_args(args)
213+
args = _parse_args(args_)
217214
_init(args.debug, args.worker_id)
218215

219216
_LG.info(args)
@@ -223,9 +220,9 @@ def worker_entrypoint(args: list[str]) -> PerfResult:
223220

224221
device = torch.device(f"cuda:{args.worker_id}")
225222

226-
ev = Event()
223+
ev: Event = Event()
227224

228-
def handler_stop_signals(_signum, _frame):
225+
def handler_stop_signals(_signum, _frame) -> None:
229226
ev.set()
230227

231228
signal.signal(signal.SIGTERM, handler_stop_signals)
@@ -267,21 +264,19 @@ def benchmark(loader: Iterator[Tensor], stop_requested: Event) -> PerfResult:
267264
return PerfResult(elapsed, num_batches, num_frames)
268265

269266

270-
def _init_logging(debug=False, worker_id=None):
267+
def _init_logging(debug: bool = False, worker_id: int | None = None) -> None:
271268
fmt = "%(asctime)s [%(filename)s:%(lineno)d] [%(levelname)s] %(message)s"
272269
if worker_id is not None:
273270
fmt = f"[{worker_id}:%(thread)d] {fmt}"
274271
level = logging.DEBUG if debug else logging.INFO
275272
logging.basicConfig(format=fmt, level=level)
276273

277274

278-
def _init(debug, worker_id):
275+
def _init(debug: bool, worker_id: int) -> None:
279276
_init_logging(debug, worker_id)
280277

281278

282-
def _parse_process_args(args):
283-
import argparse
284-
279+
def _parse_process_args(args: list[str] | None) -> tuple[Namespace, list[str]]:
285280
parser = argparse.ArgumentParser(
286281
description=__doc__,
287282
formatter_class=argparse.RawDescriptionHelpFormatter,
@@ -290,7 +285,7 @@ def _parse_process_args(args):
290285
return parser.parse_known_args(args)
291286

292287

293-
def entrypoint(args: list[str] | None = None):
288+
def entrypoint(args: list[str] | None = None) -> None:
294289
"""CLI entrypoint. Launch the worker processes,
295290
each of which load images and send them to GPU."""
296291
ns, args = _parse_process_args(args)

src/spdl/io/_composite.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import builtins
1010
import logging
1111
import warnings
12-
from collections.abc import Iterator
12+
from collections.abc import Iterator, Sequence
1313
from pathlib import Path
1414
from typing import overload, TYPE_CHECKING
1515

@@ -287,7 +287,7 @@ def _decode(src, demux_config, decode_config, filter_desc):
287287

288288
@overload
289289
def load_image_batch(
290-
srcs: list[str | bytes],
290+
srcs: Sequence[str | bytes],
291291
*,
292292
width: int | None,
293293
height: int | None,
@@ -304,7 +304,7 @@ def load_image_batch(
304304

305305
@overload
306306
def load_image_batch(
307-
srcs: list[str | bytes],
307+
srcs: Sequence[str | bytes],
308308
*,
309309
width: int | None,
310310
height: int | None,
@@ -320,7 +320,7 @@ def load_image_batch(
320320

321321

322322
def load_image_batch(
323-
srcs: list[str | bytes],
323+
srcs: Sequence[str | bytes],
324324
*,
325325
width,
326326
height,

0 commit comments

Comments
 (0)