Skip to content

Commit 4cd63de

Browse files
committed
Fixed CUDA Conda PyTorch 2.0 issues.
1 parent 2bb5c00 commit 4cd63de

File tree

5 files changed

+50
-93
lines changed

5 files changed

+50
-93
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,25 @@ Resources:
1414
Python >=3.8. Linux distribution (Ubuntu, MacOS, etc.) + CUDA > 10.0. LLM.int8() requires Turing or Ampere GPUs.
1515

1616
**Installation**:
17+
1718
``pip install bitsandbytes``
1819

20+
In some cases it can happen that you need to compile from source. In that case, you can install CUDA with the install script in the repository. No sudo is required for this install.
21+
22+
```bash
23+
wget https://raw.githubusercontent.com/TimDettmers/bitsandbytes/main/cuda_install.sh
24+
# Syntax cuda_install CUDA_VERSION INSTALL_PREFIX EXPORT_TO_BASH
25+
# CUDA_VERSION in {110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121}
26+
# EXPORT_TO_BASH in {0, 1} with 0=False and 1=True
27+
28+
# For example, the following installs CUDA 11.8 to ~/local/cuda-11.8 and exports the path to your .bashrc
29+
bash cuda install 118 ~/local 1
30+
```
31+
32+
To use a specific CUDA version just for a single compile run, you can set the variable `CUDA_HOME`, for example the following command compiles `libbitsandbytes_cuda117.so` using compiler flags for cuda11x with the cuda version at `~/local/cuda-11.7`:
33+
34+
``CUDA_HOME=~/local/cuda-11.7 CUDA_VERSION=117 make cuda11x``
35+
1936
**Using 8-bit optimizer**:
2037
1. Comment out optimizer: ``#torch.optim.Adam(....)``
2138
2. Add 8-bit optimizer of your choice ``bnb.optim.Adam8bit(....)`` (arguments stay the same)

bitsandbytes/cextension.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
setup = CUDASetup.get_instance()
1212
if setup.initialized != True:
1313
setup.run_cuda_setup()
14-
if 'BITSANDBYTES_NOWELCOME' not in os.environ or str(os.environ['BITSANDBYTES_NOWELCOME']) == '0':
15-
setup.print_log_stack()
1614

1715
lib = setup.lib
1816
try:
@@ -31,3 +29,7 @@
3129
warn("The installed version of bitsandbytes was compiled without GPU support. "
3230
"8-bit optimizers and GPU quantization are unavailable.")
3331
COMPILED_WITH_CUDA = False
32+
33+
# print the setup details after checking for errors so we do not print twice
34+
if 'BITSANDBYTES_NOWELCOME' not in os.environ or str(os.environ['BITSANDBYTES_NOWELCOME']) == '0':
35+
setup.print_log_stack()

bitsandbytes/cuda_setup/main.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,21 @@
2121
import errno
2222
import torch
2323
from warnings import warn
24+
from itertools import product
2425

2526
from pathlib import Path
2627
from typing import Set, Union
2728
from .env_vars import get_potentially_lib_path_containing_env_vars
2829

29-
CUDA_RUNTIME_LIB: str = "libcudart.so"
30+
# these are the most common libs names
31+
# libcudart.so is missing by default for a conda install with PyTorch 2.0 and instead
32+
# we have libcudart.so.11.0 which causes a lot of errors before
33+
# not sure if libcudart.so.12.0 exists in pytorch installs, but it does not hurt
34+
CUDA_RUNTIME_LIBS: list = ["libcudart.so", 'libcudart.so.11.0', 'libcudart.so.12.0']
35+
36+
# this is a order list of backup paths to search CUDA in, if it cannot be found in the main environmental paths
37+
backup_paths = []
38+
backup_paths.append('$CONDA_PREFIX/lib/libcudart.so.11.0')
3039

3140
class CUDASetup:
3241
_instance = None
@@ -98,6 +107,8 @@ def run_cuda_setup(self):
98107
package_dir = Path(__file__).parent.parent
99108
binary_path = package_dir / binary_name
100109

110+
print('bin', binary_path)
111+
101112
try:
102113
if not binary_path.exists():
103114
self.add_log_entry(f"CUDA SETUP: Required library version not found: {binary_name}. Maybe you need to compile it from source?")
@@ -117,15 +128,13 @@ def run_cuda_setup(self):
117128
self.add_log_entry('='*80)
118129
self.add_log_entry('')
119130
self.generate_instructions()
120-
self.print_log_stack()
121131
raise Exception('CUDA SETUP: Setup Failed!')
122132
self.lib = ct.cdll.LoadLibrary(binary_path)
123133
else:
124134
self.add_log_entry(f"CUDA SETUP: Loading binary {binary_path}...")
125135
self.lib = ct.cdll.LoadLibrary(binary_path)
126136
except Exception as ex:
127137
self.add_log_entry(str(ex))
128-
self.print_log_stack()
129138

130139
def add_log_entry(self, msg, is_warning=False):
131140
self.cuda_setup_log.append((msg, is_warning))
@@ -178,11 +187,12 @@ def remove_non_existent_dirs(candidate_paths: Set[Path]) -> Set[Path]:
178187

179188

180189
def get_cuda_runtime_lib_paths(candidate_paths: Set[Path]) -> Set[Path]:
181-
return {
182-
path / CUDA_RUNTIME_LIB
183-
for path in candidate_paths
184-
if (path / CUDA_RUNTIME_LIB).is_file()
185-
}
190+
paths = set()
191+
for libname in CUDA_RUNTIME_LIBS:
192+
for path in candidate_paths:
193+
if (path / libname).is_file():
194+
paths.add(path / libname)
195+
return paths
186196

187197

188198
def resolve_paths_list(paths_list_candidate: str) -> Set[Path]:
@@ -257,7 +267,7 @@ def determine_cuda_runtime_lib_path() -> Union[Path, None]:
257267
cuda_runtime_libs.update(find_cuda_lib_in(value))
258268

259269
if len(cuda_runtime_libs) == 0:
260-
CUDASetup.get_instance().add_log_entry('CUDA_SETUP: WARNING! libcudart.so not found in any environmental path. Searching /usr/local/cuda/lib64...')
270+
CUDASetup.get_instance().add_log_entry('CUDA_SETUP: WARNING! libcudart.so not found in any environmental path. Searching in backup paths...')
261271
cuda_runtime_libs.update(find_cuda_lib_in('/usr/local/cuda/lib64'))
262272

263273
warn_in_case_of_duplicates(cuda_runtime_libs)

cuda_install.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ URL121=https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installer
1717

1818
CUDA_VERSION=$1
1919
BASE_PATH=$2
20+
EXPORT_BASHRC=$3
2021

2122
if [[ -n "$CUDA_VERSION" ]]; then
2223
if [[ "$CUDA_VERSION" -eq "92" ]]; then
@@ -76,11 +77,13 @@ FILE=$(basename $URL)
7677
if [[ -n "$CUDA_VERSION" ]]; then
7778
echo $URL
7879
echo $FILE
79-
wget $URL
80-
bash $FILE --no-drm --no-man-page --override --toolkitpath=$BASE_PATH/$FOLDER/ --toolkit --silent
81-
echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$BASE_PATH/$FOLDER/lib64/" >> ~/.bashrc
82-
echo "export PATH=$PATH:$BASE_PATH/$FOLDER/bin/" >> ~/.bashrc
83-
source ~/.bashrc
80+
#wget $URL
81+
#bash $FILE --no-drm --no-man-page --override --toolkitpath=$BASE_PATH/$FOLDER/ --toolkit --silent
82+
if [ "$EXPORT_BASHRC" -eq "1" ]; then
83+
echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$BASE_PATH/$FOLDER/lib64" >> ~/.bashrc
84+
echo "export PATH=\$PATH:$BASE_PATH/$FOLDER/bin" >> ~/.bashrc
85+
source ~/.bashrc
86+
fi
8487
else
8588
echo ""
8689
fi

tests/test_cuda_setup_evaluator.py

Lines changed: 2 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,95 +5,20 @@
55

66
import bitsandbytes as bnb
77
from bitsandbytes.cuda_setup.main import (
8-
CUDA_RUNTIME_LIB,
98
determine_cuda_runtime_lib_path,
109
evaluate_cuda_setup,
1110
extract_candidate_paths,
1211
)
1312

14-
"""
15-
'LD_LIBRARY_PATH': ':/mnt/D/titus/local/cuda-11.1/lib64/'
16-
'CONDA_EXE': '/mnt/D/titus/miniconda/bin/conda'
17-
'LESSCLOSE': '/usr/bin/lesspipe %s %s'
18-
'OLDPWD': '/mnt/D/titus/src'
19-
'CONDA_PREFIX': '/mnt/D/titus/miniconda/envs/8-bit'
20-
'SSH_AUTH_SOCK': '/mnt/D/titus/.ssh/ssh-agent.tim-uw.sock'
21-
'CONDA_PREFIX_1': '/mnt/D/titus/miniconda'
22-
'PWD': '/mnt/D/titus/src/8-bit'
23-
'HOME': '/mnt/D/titus'
24-
'CONDA_PYTHON_EXE': '/mnt/D/titus/miniconda/bin/python'
25-
'CUDA_HOME': '/mnt/D/titus/local/cuda-11.1/'
26-
'TMUX': '/tmp/tmux-1007/default,59286,1'
27-
'XDG_DATA_DIRS': '/usr/local/share:/usr/share:/var/lib/snapd/desktop'
28-
'SSH_TTY': '/dev/pts/0'
29-
'MAIL': '/var/mail/titus'
30-
'SHELL': '/bin/bash'
31-
'DBUS_SESSION_BUS_ADDRESS': 'unix:path=/run/user/1007/bus'
32-
'XDG_RUNTIME_DIR': '/run/user/1007'
33-
'PATH': '/mnt/D/titus/miniconda/envs/8-bit/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/mnt/D/titus/local/cuda-11.1/bin'
34-
'LESSOPEN': '| /usr/bin/lesspipe %s'
35-
'_': '/mnt/D/titus/miniconda/envs/8-bit/bin/python'
36-
# any that include 'CONDA' that are not 'CONDA_PREFIX'
3713

38-
# we search for
39-
'CUDA_HOME': '/mnt/D/titus/local/cuda-11.1/'
40-
"""
41-
42-
43-
class InputAndExpectedOutput(NamedTuple):
44-
input: str
45-
output: str
46-
47-
48-
HAPPY_PATH__LD_LIB_TEST_PATHS: List[InputAndExpectedOutput] = [
49-
(
50-
f"some/other/dir:dir/with/{CUDA_RUNTIME_LIB}",
51-
f"dir/with/{CUDA_RUNTIME_LIB}",
52-
),
53-
(
54-
f":some/other/dir:dir/with/{CUDA_RUNTIME_LIB}",
55-
f"dir/with/{CUDA_RUNTIME_LIB}",
56-
),
57-
(
58-
f"some/other/dir:dir/with/{CUDA_RUNTIME_LIB}:",
59-
f"dir/with/{CUDA_RUNTIME_LIB}",
60-
),
61-
(
62-
f"some/other/dir::dir/with/{CUDA_RUNTIME_LIB}",
63-
f"dir/with/{CUDA_RUNTIME_LIB}",
64-
),
65-
(
66-
f"dir/with/{CUDA_RUNTIME_LIB}:some/other/dir",
67-
f"dir/with/{CUDA_RUNTIME_LIB}",
68-
),
69-
(
70-
f"dir/with/{CUDA_RUNTIME_LIB}:other/dir/libcuda.so",
71-
f"dir/with/{CUDA_RUNTIME_LIB}",
72-
),
73-
]
74-
75-
76-
@pytest.fixture(params=HAPPY_PATH__LD_LIB_TEST_PATHS)
77-
def happy_path_path_string(tmpdir, request):
78-
for path in extract_candidate_paths(request.param):
79-
test_dir.mkdir()
80-
if CUDA_RUNTIME_LIB in path:
81-
(test_input / CUDA_RUNTIME_LIB).touch()
82-
83-
UNHAPPY_PATH__LD_LIB_TEST_PATHS = [
84-
f"a/b/c/{CUDA_RUNTIME_LIB}:d/e/f/{CUDA_RUNTIME_LIB}",
85-
f"a/b/c/{CUDA_RUNTIME_LIB}:d/e/f/{CUDA_RUNTIME_LIB}:g/h/j/{CUDA_RUNTIME_LIB}",
86-
]
87-
88-
89-
def test_full_system():
14+
def test_cuda_full_system():
9015
## this only tests the cuda version and not compute capability
9116

9217
# if CONDA_PREFIX exists, it has priority before all other env variables
9318
# but it does not contain the library directly, so we need to look at the a sub-folder
9419
version = ""
9520
if "CONDA_PREFIX" in os.environ:
96-
ls_output, err = bnb.utils.execute_and_return(f'ls -l {os.environ["CONDA_PREFIX"]}/lib/libcudart.so')
21+
ls_output, err = bnb.utils.execute_and_return(f'ls -l {os.environ["CONDA_PREFIX"]}/lib/libcudart.so.11.0')
9722
major, minor, revision = (ls_output.split(" ")[-1].replace("libcudart.so.", "").split("."))
9823
version = float(f"{major}.{minor}")
9924

0 commit comments

Comments
 (0)