Fix bitsandbytes zombie module breaking test collection on CPU runners (#7580)
* Fix bitsandbytes zombie module breaking test collection A partially failed `import bitsandbytes` leaves the package half-imported: CPython evicts only the parent from sys.modules and keeps every submodule it had already loaded. The next import re-executes __init__ but every `from .x import y` is served from cache, so the submodule attributes are never rebound. The package imports "successfully" while `bnb.functional` is gone. Bind the submodule via `import bitsandbytes.functional as bnb_functional`, which reads sys.modules directly and survives that state, and import bitsandbytes in tests/conftest.py on the real CPU path before torch.cuda.is_available() is mocked, so the half-imported state is never created in the first place. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
f44379d9e8
commit
7b068090b2
2 changed files with 23 additions and 10 deletions
|
|
@ -303,13 +303,19 @@ if DEVICE_TYPE == "cuda":
|
||||||
# Try loading bitsandbytes and triton
|
# Try loading bitsandbytes and triton
|
||||||
try:
|
try:
|
||||||
import bitsandbytes as bnb
|
import bitsandbytes as bnb
|
||||||
|
|
||||||
|
# Bind the submodule by name: a half-imported bitsandbytes leaves the parent
|
||||||
|
# without a `functional` attribute, which would otherwise be misreported below
|
||||||
|
# as a CUDA linking failure. See unsloth/kernels/utils.py.
|
||||||
|
import bitsandbytes.functional as bnb_functional
|
||||||
except:
|
except:
|
||||||
print(
|
print(
|
||||||
"Unsloth: `bitsandbytes` is not installed - 4bit QLoRA unallowed, but 16bit and full finetuning works!"
|
"Unsloth: `bitsandbytes` is not installed - 4bit QLoRA unallowed, but 16bit and full finetuning works!"
|
||||||
)
|
)
|
||||||
bnb = None
|
bnb = None
|
||||||
|
bnb_functional = None
|
||||||
try:
|
try:
|
||||||
cdequantize_blockwise_fp32 = bnb.functional.lib.cdequantize_blockwise_fp32
|
cdequantize_blockwise_fp32 = bnb_functional.lib.cdequantize_blockwise_fp32
|
||||||
libcuda_dirs()
|
libcuda_dirs()
|
||||||
except:
|
except:
|
||||||
if hasattr(os, "geteuid") and os.geteuid() == 0:
|
if hasattr(os, "geteuid") and os.geteuid() == 0:
|
||||||
|
|
@ -351,7 +357,7 @@ if DEVICE_TYPE == "cuda":
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
from triton.common.build import libcuda_dirs
|
from triton.common.build import libcuda_dirs
|
||||||
cdequantize_blockwise_fp32 = bnb.functional.lib.cdequantize_blockwise_fp32
|
cdequantize_blockwise_fp32 = bnb_functional.lib.cdequantize_blockwise_fp32
|
||||||
libcuda_dirs()
|
libcuda_dirs()
|
||||||
except:
|
except:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
|
|
|
||||||
|
|
@ -136,11 +136,18 @@ def calculate_settings(
|
||||||
HAS_CUDA_STREAM = False
|
HAS_CUDA_STREAM = False
|
||||||
try:
|
try:
|
||||||
import bitsandbytes as bnb
|
import bitsandbytes as bnb
|
||||||
|
|
||||||
|
# If an earlier `import bitsandbytes` died inside __init__, CPython evicts only
|
||||||
|
# the parent from sys.modules and keeps its submodules, so this retry re-executes
|
||||||
|
# __init__ without rebinding `bnb.functional`. `import x.y as z` reads sys.modules
|
||||||
|
# directly and survives that, plain attribute access does not.
|
||||||
|
import bitsandbytes.functional as bnb_functional
|
||||||
except Exception:
|
except Exception:
|
||||||
# device_type.py already degrades to 16bit/full finetuning when bnb is missing
|
# device_type.py already degrades to 16bit/full finetuning when bnb is missing
|
||||||
# (e.g. gfx906, whose generic wheel has no kernels). Keep the import working and
|
# (e.g. gfx906, whose generic wheel has no kernels). Keep the import working and
|
||||||
# fail only if a 4bit path is actually entered.
|
# fail only if a 4bit path is actually entered.
|
||||||
bnb = None
|
bnb = None
|
||||||
|
bnb_functional = None
|
||||||
|
|
||||||
|
|
||||||
def _bnb_required(*args, **kwargs):
|
def _bnb_required(*args, **kwargs):
|
||||||
|
|
@ -153,7 +160,7 @@ def _bnb_required(*args, **kwargs):
|
||||||
if bnb is not None:
|
if bnb is not None:
|
||||||
# https://github.com/bitsandbytes-foundation/bitsandbytes/pull/1330/files
|
# https://github.com/bitsandbytes-foundation/bitsandbytes/pull/1330/files
|
||||||
HAS_CUDA_STREAM = Version(bnb.__version__) > Version("0.43.3")
|
HAS_CUDA_STREAM = Version(bnb.__version__) > Version("0.43.3")
|
||||||
get_ptr = bnb.functional.get_ptr
|
get_ptr = bnb_functional.get_ptr
|
||||||
else:
|
else:
|
||||||
get_ptr = _bnb_required
|
get_ptr = _bnb_required
|
||||||
|
|
||||||
|
|
@ -263,18 +270,18 @@ if bnb is None or not native_kernels_ready(bnb, DEVICE_TYPE):
|
||||||
cgemm_4bit_inference_naive_fp16 = _bnb_required
|
cgemm_4bit_inference_naive_fp16 = _bnb_required
|
||||||
cgemm_4bit_inference_naive_bf16 = _bnb_required
|
cgemm_4bit_inference_naive_bf16 = _bnb_required
|
||||||
else:
|
else:
|
||||||
cdequantize_blockwise_fp32 = bnb.functional.lib.cdequantize_blockwise_fp32
|
cdequantize_blockwise_fp32 = bnb_functional.lib.cdequantize_blockwise_fp32
|
||||||
cdequantize_blockwise_fp16_nf4 = bnb.functional.lib.cdequantize_blockwise_fp16_nf4
|
cdequantize_blockwise_fp16_nf4 = bnb_functional.lib.cdequantize_blockwise_fp16_nf4
|
||||||
cdequantize_blockwise_bf16_nf4 = bnb.functional.lib.cdequantize_blockwise_bf16_nf4
|
cdequantize_blockwise_bf16_nf4 = bnb_functional.lib.cdequantize_blockwise_bf16_nf4
|
||||||
|
|
||||||
if DEVICE_TYPE == "xpu":
|
if DEVICE_TYPE == "xpu":
|
||||||
# https://github.com/bitsandbytes-foundation/bitsandbytes/blob/c3b8de268fdb55a88f92feada23fc811a1e6877a/bitsandbytes/backends/xpu/ops.py#L115
|
# https://github.com/bitsandbytes-foundation/bitsandbytes/blob/c3b8de268fdb55a88f92feada23fc811a1e6877a/bitsandbytes/backends/xpu/ops.py#L115
|
||||||
# for xpu, inference gemv using above link
|
# for xpu, inference gemv using above link
|
||||||
cgemm_4bit_inference_naive_fp16 = bnb.functional.lib.cgemv_4bit_inference_fp16
|
cgemm_4bit_inference_naive_fp16 = bnb_functional.lib.cgemv_4bit_inference_fp16
|
||||||
cgemm_4bit_inference_naive_bf16 = bnb.functional.lib.cgemv_4bit_inference_bf16
|
cgemm_4bit_inference_naive_bf16 = bnb_functional.lib.cgemv_4bit_inference_bf16
|
||||||
else:
|
else:
|
||||||
cgemm_4bit_inference_naive_fp16 = bnb.functional.lib.cgemm_4bit_inference_naive_fp16
|
cgemm_4bit_inference_naive_fp16 = bnb_functional.lib.cgemm_4bit_inference_naive_fp16
|
||||||
cgemm_4bit_inference_naive_bf16 = bnb.functional.lib.cgemm_4bit_inference_naive_bf16
|
cgemm_4bit_inference_naive_bf16 = bnb_functional.lib.cgemm_4bit_inference_naive_bf16
|
||||||
|
|
||||||
|
|
||||||
torch_device_stream = (
|
torch_device_stream = (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue