Skip to content

Commit e8cc7f9

Browse files
authored
Simplify the extension initialization process (#1734)
Calling `torch.[ops|classes].load_library(<PATH_TO_LIBRARY_FILE>)` is problematic in case `torchaudio` is deployed with PEX format, because the library file does not exist as a file. Our extension module, when it exists, is guaranteed to have PyBind11 binding even when no function is bound. This allows to load the library using the regular `import` statement in Python, and it works even in PEX format. When the library is loaded, the static initialization kicks in and the custom kernels bound via TorchScript also become available. This removes the need to call `torch.[ops|classe].load_library`. This works even when the implementation of custom kernel is stripped from `_torchaudio.so` so long as `_torchaudio.so` properly depend on the library that has the kernel implementations and static initialization.
1 parent a525abb commit e8cc7f9

File tree

3 files changed

+35
-36
lines changed

3 files changed

+35
-36
lines changed

torchaudio/__init__.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
1-
from . import extension # noqa: F401
21
from torchaudio._internal import module_utils as _mod_utils # noqa: F401
2+
3+
if _mod_utils.is_module_available('torchaudio._torchaudio'):
4+
# Note this import has two purposes
5+
# 1. Make _torchaudio accessible by the other modules (regular import)
6+
# 2. Register torchaudio's custom ops bound via TorchScript
7+
#
8+
# For 2, normally function calls `torch.ops.load_library` and `torch.classes.load_library`
9+
# are used. However, in our cases, this is inconvenient and unnecessary.
10+
#
11+
# - Why inconvenient?
12+
# When torchaudio is deployed with `pex` format, all the files are deployed as a single zip
13+
# file, and the extension module is not present as a file with full path. Therefore it is not
14+
# possible to pass the path to library to `torch.[ops|classes].load_library` functions.
15+
#
16+
# - Why unnecessary?
17+
# When torchaudio extension module (C++ module) is available, it is assumed that
18+
# the extension contains both TorchScript-based binding and PyBind11-based binding.*
19+
# Under this assumption, simply performing `from torchaudio import _torchaudio` will load the
20+
# library which contains TorchScript-based binding as well, and the functions/classes bound
21+
# via TorchScript become accessible under `torch.ops` and `torch.classes`.
22+
#
23+
# *Note that this holds true even when these two bindings are split into two library files and
24+
# the library that contains PyBind11-based binding (`_torchaudio.so` in the following diagram)
25+
# depends on the other one (`libtorchaudio.so`), because when the process tries to load
26+
# `_torchaudio.so` it detects undefined symbols from `libtorchaudio.so` and will automatically
27+
# loads `libtorchaudio.so`. (given that the library is found in a search path)
28+
#
29+
# [libtorchaudio.so] <- [_torchaudio.so]
30+
#
31+
#
32+
from torchaudio import _torchaudio # noqa
33+
else:
34+
import warnings
35+
warnings.warn('torchaudio C++ extension is not available.')
36+
337
from torchaudio import (
438
compliance,
539
datasets,

torchaudio/extension/__init__.py

Lines changed: 0 additions & 12 deletions
This file was deleted.

torchaudio/extension/extension.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)