Skip to content

Commit 0be7e78

Browse files
committed
Revert "[torchcodec] Add CUDA support to SimpleVideoDecoder (#146)"
This reverts commit ec5e63a.
1 parent f938db8 commit 0be7e78

File tree

4 files changed

+27
-92
lines changed

4 files changed

+27
-92
lines changed

benchmarks/decoders/gpu_benchmark.py

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,40 @@
88
from torchvision.transforms import Resize
99

1010

11-
def transfer_and_resize_frame(frame):
12-
# This should be a no-op if the frame is already on the GPU.
13-
frame = frame.to("cuda:0")
11+
def transfer_and_resize_frame(frame, device):
12+
# This should be a no-op if the frame is already on the device.
13+
frame = frame.to(device)
1414
frame = Resize((256, 256))(frame)
1515
return frame
1616

1717

18-
def decode_full_video(video_path, device_string, do_gpu_preproc):
19-
decoder = torchcodec.decoders.SimpleVideoDecoder(
20-
video_path, device=torch.device(device_string)
18+
def decode_full_video(video_path, decode_device):
19+
decoder = torchcodec.decoders._core.create_from_file(video_path)
20+
num_threads = None
21+
if "cuda" in decode_device:
22+
num_threads = 1
23+
torchcodec.decoders._core.add_video_stream(
24+
decoder, stream_index=0, device_string=decode_device, num_threads=num_threads
2125
)
2226
start_time = time.time()
2327
frame_count = 0
24-
for frame in decoder:
25-
# You can do a resize to simulate extra preproc work that happens
26-
# on the GPU by uncommenting the following line:
27-
if do_gpu_preproc:
28-
frame = transfer_and_resize_frame(frame)
29-
frame_count += 1
28+
while True:
29+
try:
30+
frame, *_ = torchcodec.decoders._core.get_next_frame(decoder)
31+
# You can do a resize to simulate extra preproc work that happens
32+
# on the GPU by uncommenting the following line:
33+
# frame = transfer_and_resize_frame(frame, decode_device)
34+
35+
frame_count += 1
36+
except Exception as e:
37+
print("EXCEPTION", e)
38+
break
39+
# print(f"current {frame_count=}", flush=True)
3040
end_time = time.time()
3141
elapsed = end_time - start_time
3242
fps = frame_count / (end_time - start_time)
3343
print(
34-
f"****** DECODED full video {device_string=} {frame_count=} {elapsed=} {fps=}"
44+
f"****** DECODED full video {decode_device=} {frame_count=} {elapsed=} {fps=}"
3545
)
3646
return frame_count, end_time - start_time
3747

@@ -59,15 +69,6 @@ def main():
5969
"to measure the cold start time."
6070
),
6171
)
62-
parser.add_argument(
63-
"--do_gpu_preproc",
64-
action=argparse.BooleanOptionalAction,
65-
default=True,
66-
help=(
67-
"Do a transfer to GPU and resize operation after the decode to "
68-
"simulate a real-world transform."
69-
),
70-
)
7172
args = parser.parse_args()
7273
video_path = args.video
7374

@@ -77,23 +78,17 @@ def main():
7778
decode_full_video(video_path, device)
7879
return
7980

80-
label = "Decode"
81-
if args.do_gpu_preproc:
82-
label += " + GPU Preproc"
83-
label += " Time"
84-
8581
results = []
8682
for device in args.devices.split(","):
8783
print("device", device)
8884
t = benchmark.Timer(
89-
stmt="decode_full_video(video_path, device, do_gpu_preproc)",
85+
stmt="decode_full_video(video_path, device)",
9086
globals={
9187
"device": device,
9288
"video_path": video_path,
9389
"decode_full_video": decode_full_video,
94-
"do_gpu_preproc": args.do_gpu_preproc,
9590
},
96-
label=label,
91+
label="Decode+Resize Time",
9792
sub_label=f"video={os.path.basename(video_path)}",
9893
description=f"decode_device={device}",
9994
).blocked_autorange()

examples/basic_example.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,3 @@ def plot(frames: torch.Tensor, title : Optional[str] = None):
172172
plot(frame_at_2_seconds.data, "Frame displayed at 2 seconds")
173173
plot(first_two_seconds.data, "Frames displayed during [0, 2) seconds")
174174

175-
# %%
176-
# Using a CUDA GPU to accelerate decoding
177-
# ---------------------------------------
178-
#
179-
# If you have a CUDA GPU that has NVDEC, you can decode on the GPU.
180-
if torch.cuda.is_available():
181-
cuda_decoder = SimpleVideoDecoder(raw_video_bytes, device="cuda:0")
182-
cuda_frame = cuda_decoder.get_frame_displayed_at(seconds=2)
183-
print(cuda_frame.data.device) # should be cuda:0
184-
plot(cuda_frame.data.to("cpu"), "Frame displayed at 2 seconds on CUDA")

src/torchcodec/decoders/_simple_video_decoder.py

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pathlib import Path
1010
from typing import Iterable, Iterator, Literal, Tuple, Union
1111

12-
from torch import device as torch_device, Tensor
12+
from torch import Tensor
1313

1414
from torchcodec.decoders import _core as core
1515

@@ -89,14 +89,6 @@ class SimpleVideoDecoder:
8989
This can be either "NCHW" (default) or "NHWC", where N is the batch
9090
size, C is the number of channels, H is the height, and W is the
9191
width of the frames.
92-
device (torch.device, optional): The device to use for decoding.
93-
Currently we only support CPU and CUDA devices. If CUDA is used,
94-
we use NVDEC and CUDA to do decoding and color-conversion
95-
respectively. The resulting frame is left on the GPU for further
96-
processing.
97-
You can either pass in a string like "cpu" or "cuda:0" or a
98-
torch.device like torch.device("cuda:0").
99-
Default: ``torch.device("cpu")``.
10092
10193
.. note::
10294
@@ -114,7 +106,6 @@ def __init__(
114106
self,
115107
source: Union[str, Path, bytes, Tensor],
116108
dimension_order: Literal["NCHW", "NHWC"] = "NCHW",
117-
device: Union[str, torch_device] = torch_device("cpu"),
118109
):
119110
if isinstance(source, str):
120111
self._decoder = core.create_from_file(source)
@@ -138,20 +129,7 @@ def __init__(
138129
)
139130

140131
core.scan_all_streams_to_update_metadata(self._decoder)
141-
num_threads = None
142-
if isinstance(device, str):
143-
device = torch_device(device)
144-
if device.type == "cuda":
145-
# Using multiple CPU threads seems to slow down decoding on CUDA.
146-
# CUDA internally uses dedicated hardware to do decoding so we
147-
# don't need CPU software threads here.
148-
num_threads = 1
149-
core.add_video_stream(
150-
self._decoder,
151-
dimension_order=dimension_order,
152-
device_string=str(device),
153-
num_threads=num_threads,
154-
)
132+
core.add_video_stream(self._decoder, dimension_order=dimension_order)
155133

156134
self.metadata, self._stream_index = _get_and_validate_stream_metadata(
157135
self._decoder

test/decoders/test_simple_video_decoder.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,6 @@ def test_create_fails(self):
4545
with pytest.raises(TypeError, match="Unknown source type"):
4646
decoder = SimpleVideoDecoder(123) # noqa
4747

48-
def test_can_accept_devices(self):
49-
# You can pass a CPU device as a string...<contd>
50-
decoder = SimpleVideoDecoder(NASA_VIDEO.path, device="cpu")
51-
assert_tensor_equal(decoder[0], NASA_VIDEO.get_frame_data_by_index(0))
52-
53-
# ...or as a torch.device.
54-
decoder = SimpleVideoDecoder(NASA_VIDEO.path, device=torch.device("cpu"))
55-
assert_tensor_equal(decoder[0], NASA_VIDEO.get_frame_data_by_index(0))
56-
57-
if torch.cuda.is_available():
58-
# You can pass a CUDA device as a string...<contd>
59-
decoder = SimpleVideoDecoder(NASA_VIDEO.path, device="cuda")
60-
frame = decoder[0]
61-
assert frame.device.type == "cuda"
62-
assert frame.shape == torch.Size(
63-
[NASA_VIDEO.num_color_channels, NASA_VIDEO.height, NASA_VIDEO.width]
64-
)
65-
66-
# ...or as a torch.device.
67-
decoder = SimpleVideoDecoder(NASA_VIDEO.path, device=torch.device("cuda"))
68-
frame = decoder[0]
69-
assert frame.device.type == "cuda"
70-
assert frame.shape == torch.Size(
71-
[NASA_VIDEO.num_color_channels, NASA_VIDEO.height, NASA_VIDEO.width]
72-
)
73-
# TODO: compare tensor values too. We don't compare values because
74-
# the exact values are hardware-dependent.
75-
7648
def test_getitem_int(self):
7749
decoder = SimpleVideoDecoder(NASA_VIDEO.path)
7850

0 commit comments

Comments
 (0)