Skip to content

Commit d1dd4fe

Browse files
committed
fix(interservice): fix triton LSA test library loading and allocator robustness
1 parent f7b3ee2 commit d1dd4fe

2 files changed

Lines changed: 104 additions & 23 deletions

File tree

plugin/interservice/flagcx_wrapper.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,11 +411,40 @@ class FLAGCXLibrary:
411411
# to the corresponding dictionary
412412
path_to_dict_mapping: Dict[str, Dict[str, Any]] = {}
413413

414-
def __init__(self, so_file: Optional[str] = None):
414+
@staticmethod
415+
def _find_default_library() -> str:
416+
import os
417+
# 1. Check FLAGCX_PATH env var
418+
flagcx_path = os.environ.get("FLAGCX_PATH")
419+
if flagcx_path:
420+
so_path = os.path.join(flagcx_path, "lib", "libflagcx.so")
421+
if os.path.isfile(so_path):
422+
return so_path
423+
raise FileNotFoundError(
424+
f"FLAGCX_PATH is set to '{flagcx_path}' but "
425+
f"'{so_path}' does not exist. "
426+
f"Please build FlagCX or check FLAGCX_PATH."
427+
)
428+
# 2. Fall back to <repo_root>/build/lib/libflagcx.so
429+
repo_root = os.path.abspath(
430+
os.path.join(os.path.dirname(__file__), "..", "..")
431+
)
432+
so_path = os.path.join(repo_root, "build", "lib", "libflagcx.so")
433+
if os.path.isfile(so_path):
434+
return so_path
435+
raise FileNotFoundError(
436+
f"Cannot find libflagcx.so. Searched:\n"
437+
f" - $FLAGCX_PATH/lib/libflagcx.so (FLAGCX_PATH not set)\n"
438+
f" - {so_path} (not found)\n"
439+
f"Please set FLAGCX_PATH or build FlagCX first."
440+
)
415441

442+
def __init__(self, so_file: Optional[str] = None):
443+
if so_file is None:
444+
so_file = FLAGCXLibrary._find_default_library()
416445

417446
try:
418-
if so_file not in FLAGCXLibrary.path_to_dict_mapping:
447+
if so_file not in FLAGCXLibrary.path_to_library_cache:
419448
lib = ctypes.CDLL(so_file)
420449
FLAGCXLibrary.path_to_library_cache[so_file] = lib
421450
self.lib = FLAGCXLibrary.path_to_library_cache[so_file]
@@ -438,7 +467,8 @@ def __init__(self, so_file: Optional[str] = None):
438467

439468
def __del__(self):
440469
# free flagcx handler
441-
self.FLAGCX_CHECK(self._funcs["flagcxHandleFree"](self.handler))
470+
if hasattr(self, '_funcs') and hasattr(self, 'handler'):
471+
self.FLAGCX_CHECK(self._funcs["flagcxHandleFree"](self.handler))
442472

443473
def flagcxGetErrorString(self, result: flagcxResult_t) -> str:
444474
return self._funcs["flagcxGetErrorString"](result).decode("utf-8")

plugin/interservice/test_triton_lsa.py

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@
4444
os.path.join(os.path.dirname(__file__), "../../flagcx/include"),
4545
)
4646

47+
# FlagCX library path for linking
48+
FLAGCX_LIB_PATH = os.environ.get(
49+
"FLAGCX_LIB_PATH",
50+
os.path.join(os.path.dirname(__file__), "../../build/lib"),
51+
)
52+
4753
# ============================================================
4854
# FlagCX pluggable allocator (wraps flagcxMemAlloc/flagcxMemFree)
4955
# ============================================================
@@ -70,29 +76,69 @@
7076
}
7177
"""
7278

79+
_allocator = None
80+
_allocator_wrapper = None
81+
_mem_pool = None
82+
_flagcx_allocator_failed_to_compile = False
83+
84+
85+
def compile_flagcx_allocator():
86+
"""Compile the FlagCX allocator extension. Called once, result cached."""
87+
global _allocator, _allocator_wrapper, _flagcx_allocator_failed_to_compile
88+
try:
89+
out_dir = tempfile.gettempdir()
90+
lib_name = "flagcx_allocator"
91+
92+
load_inline(
93+
name=lib_name,
94+
cpp_sources=flagcx_allocator_source,
95+
with_cuda=True,
96+
extra_ldflags=[f"-L{FLAGCX_LIB_PATH}", "-lflagcx",
97+
f"-Wl,-rpath,{FLAGCX_LIB_PATH}"],
98+
verbose=False,
99+
is_python_module=False,
100+
build_directory=out_dir,
101+
extra_include_paths=[FLAGCX_INCLUDE_PATH],
102+
)
103+
104+
_allocator_wrapper = CUDAPluggableAllocator(
105+
f"{out_dir}/{lib_name}.so",
106+
"flagcx_alloc_plug",
107+
"flagcx_free_plug",
108+
)
109+
_allocator = _allocator_wrapper.allocator()
110+
except Exception as e:
111+
_flagcx_allocator_failed_to_compile = True
112+
print(
113+
f"[WARNING] Failed to compile FlagCX memory allocator: {e}\n"
114+
f" Ensure FLAGCX_LIB_PATH ({FLAGCX_LIB_PATH}) contains libflagcx.so\n"
115+
f" and FLAGCX_INCLUDE_PATH ({FLAGCX_INCLUDE_PATH}) contains flagcx.h"
116+
)
117+
73118

74119
def get_flagcx_mem_pool():
75-
"""Compile and return a PyTorch MemPool that uses flagcxMemAlloc."""
76-
out_dir = tempfile.gettempdir()
77-
lib_name = "flagcx_allocator"
78-
79-
load_inline(
80-
name=lib_name,
81-
cpp_sources=flagcx_allocator_source,
82-
with_cuda=True,
83-
extra_ldflags=["-lflagcx"],
84-
verbose=False,
85-
is_python_module=False,
86-
build_directory=out_dir,
87-
extra_include_paths=[FLAGCX_INCLUDE_PATH],
88-
)
120+
"""Return a cached PyTorch MemPool backed by flagcxMemAlloc."""
121+
global _mem_pool, _flagcx_allocator_failed_to_compile
122+
if _mem_pool is None and not _flagcx_allocator_failed_to_compile:
123+
compile_flagcx_allocator()
124+
if _allocator is not None:
125+
_mem_pool = torch.cuda.MemPool(_allocator)
126+
return _mem_pool
89127

90-
allocator_wrapper = CUDAPluggableAllocator(
91-
f"{out_dir}/{lib_name}.so",
92-
"flagcx_alloc_plug",
93-
"flagcx_free_plug",
94-
)
95-
return torch.cuda.MemPool(allocator_wrapper.allocator())
128+
129+
def _cleanup_flagcx_mem_pool():
130+
global _mem_pool
131+
_mem_pool = None
132+
133+
134+
def _cleanup_flagcx_allocator_wrapper():
135+
global _allocator_wrapper
136+
_allocator_wrapper = None
137+
138+
139+
import atexit
140+
atexit.register(_cleanup_flagcx_mem_pool)
141+
atexit.register(_cleanup_flagcx_allocator_wrapper)
96142

97143

98144
# ============================================================
@@ -181,6 +227,11 @@ def main():
181227
buf_size = N * 4 # float32
182228

183229
flagcx_pool = get_flagcx_mem_pool()
230+
if flagcx_pool is None:
231+
raise RuntimeError(
232+
"Failed to initialize FlagCX memory pool. "
233+
"Check compilation warnings above."
234+
)
184235
with torch.cuda.use_mem_pool(flagcx_pool):
185236
buf_tensor = torch.full((N,), float(rank), dtype=torch.float32, device="cuda")
186237

0 commit comments

Comments
 (0)