Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
bitsandbytes
Commits
dd50382b
You need to sign in or sign up before continuing.
Commit
dd50382b
authored
Jul 31, 2022
by
Tim Dettmers
Browse files
Full evaluate_cuda setup with integration test.
parent
5d90b38c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
123 additions
and
13 deletions
+123
-13
bitsandbytes/cextension.py
bitsandbytes/cextension.py
+26
-1
bitsandbytes/cuda_setup.py
bitsandbytes/cuda_setup.py
+77
-7
install_cuda.sh
install_cuda.sh
+0
-5
tests/test_cuda_setup_evaluator.py
tests/test_cuda_setup_evaluator.py
+20
-0
No files found.
bitsandbytes/cextension.py
View file @
dd50382b
import
ctypes
as
ct
import
os
from
warnings
import
warn
from
bitsandbytes.cuda_setup
import
evaluate_cuda_setup
lib
=
ct
.
cdll
.
LoadLibrary
(
os
.
path
.
dirname
(
__file__
)
+
'/libbitsandbytes.so'
)
class
CUDALibrary_Singleton
(
object
):
_instance
=
None
def
__init__
(
self
):
raise
RuntimeError
(
'Call get_instance() instead'
)
def
initialize
(
self
):
self
.
context
=
{}
binary_name
=
evaluate_cuda_setup
()
if
not
os
.
path
.
exists
(
os
.
path
.
dirname
(
__file__
)
+
f
'/
{
binary_name
}
'
):
print
(
f
'TODO: compile library for specific version:
{
binary_name
}
'
)
print
(
'defaulting to libbitsandbytes.so'
)
self
.
lib
=
ct
.
cdll
.
LoadLibrary
(
os
.
path
.
dirname
(
__file__
)
+
'/libbitsandbytes.so'
)
else
:
self
.
lib
=
ct
.
cdll
.
LoadLibrary
(
os
.
path
.
dirname
(
__file__
)
+
f
'/
{
binary_name
}
'
)
@
classmethod
def
get_instance
(
cls
):
if
cls
.
_instance
is
None
:
cls
.
_instance
=
cls
.
__new__
(
cls
)
cls
.
_instance
.
initialize
()
return
cls
.
_instance
lib
=
CUDALibrary_Singleton
.
get_instance
().
lib
try
:
lib
.
cadam32bit_g32
lib
.
get_context
.
restype
=
ct
.
c_void_p
...
...
bitsandbytes/cuda_setup.py
View file @
dd50382b
...
...
@@ -23,6 +23,58 @@ from pathlib import Path
from
typing
import
Set
,
Union
from
.utils
import
warn_of_missing_prerequisite
,
print_err
import
ctypes
import
shlex
import
subprocess
def
execute_and_return
(
strCMD
):
proc
=
subprocess
.
Popen
(
shlex
.
split
(
strCMD
),
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
out
,
err
=
proc
.
communicate
()
out
,
err
=
out
.
decode
(
"UTF-8"
).
strip
(),
err
.
decode
(
"UTF-8"
).
strip
()
return
out
,
err
def
check_cuda_result
(
cuda
,
result_val
):
if
result_val
!=
0
:
cuda
.
cuGetErrorString
(
result_val
,
ctypes
.
byref
(
error_str
))
print
(
f
"Count not initialize CUDA - failure!"
)
raise
Exception
(
'CUDA excepion!'
)
return
result_val
# taken from https://gist.github.com/f0k/63a664160d016a491b2cbea15913d549
def
get_compute_capability
():
libnames
=
(
'libcuda.so'
,
'libcuda.dylib'
,
'cuda.dll'
)
for
libname
in
libnames
:
try
:
cuda
=
ctypes
.
CDLL
(
libname
)
except
OSError
:
continue
else
:
break
else
:
raise
OSError
(
"could not load any of: "
+
' '
.
join
(
libnames
))
nGpus
=
ctypes
.
c_int
()
cc_major
=
ctypes
.
c_int
()
cc_minor
=
ctypes
.
c_int
()
result
=
ctypes
.
c_int
()
device
=
ctypes
.
c_int
()
context
=
ctypes
.
c_void_p
()
error_str
=
ctypes
.
c_char_p
()
result
=
check_cuda_result
(
cuda
,
cuda
.
cuInit
(
0
))
result
=
check_cuda_result
(
cuda
,
cuda
.
cuDeviceGetCount
(
ctypes
.
byref
(
nGpus
)))
ccs
=
[]
for
i
in
range
(
nGpus
.
value
):
result
=
check_cuda_result
(
cuda
,
cuda
.
cuDeviceGet
(
ctypes
.
byref
(
device
),
i
))
result
=
check_cuda_result
(
cuda
,
cuda
.
cuDeviceComputeCapability
(
ctypes
.
byref
(
cc_major
),
ctypes
.
byref
(
cc_minor
),
device
))
ccs
.
append
(
f
'
{
cc_major
.
value
}
.
{
cc_minor
.
value
}
'
)
#TODO: handle different compute capabilities; for now, take the max
ccs
.
sort
()
return
ccs
[
-
1
]
CUDA_RUNTIME_LIB
:
str
=
"libcudart.so"
...
...
@@ -72,12 +124,30 @@ def get_cuda_runtime_lib_path(
raise
FileNotFoundError
(
err_msg
)
single_cuda_runtime_lib_dir
=
next
(
iter
(
cuda_runtime_libs
))
return
ld_library_paths
return
single_cuda_runtime_lib_dir
def
evaluate_cuda_setup
():
# - if paths faulty, return meaningful error
# - else:
# - determine CUDA version
# - determine capabilities
# - based on that set the default path
pass
cuda_path
=
get_cuda_runtime_lib_path
()
cc
=
get_compute_capability
()
binary_name
=
'libbitsandbytes_cpu.so'
has_gpu
=
cc
!=
''
if
not
has_gpu
:
print
(
'WARNING: No GPU detected! Check our CUDA paths. Processding to load CPU-only library...'
)
return
binary_name
has_cublaslt
=
cc
in
[
'7.5'
,
'8.0'
,
'8.6'
]
# TODO:
# (1) Model missing cases (no CUDA installed by CUDA driver (nvidia-smi accessible)
# (2) Multiple CUDA versions installed
cuda_home
=
str
(
Path
(
cuda_path
).
parent
.
parent
)
ls_output
,
err
=
execute_and_return
(
f
'
{
cuda_home
}
/bin/nvcc --version'
)
cuda_version
=
ls_output
.
split
(
'
\n
'
)[
3
].
split
(
','
)[
-
1
].
strip
().
lower
().
replace
(
'v'
,
''
)
major
,
minor
,
revision
=
cuda_version
.
split
(
'.'
)
cuda_version_string
=
f
'
{
major
}{
minor
}
'
binary_name
=
f
'libbitsandbytes_cuda
{
cuda_version_string
}
_
{
(
"cublaslt"
if
has_cublaslt
else
""
)
}
.so'
return
binary_name
install_cuda.sh
deleted
100644 → 0
View file @
5d90b38c
wget https://developer.download.nvidia.com/compute/cuda/11.1.1/local_installers/cuda_11.1.1_455.32.00_linux.run
bash cuda_11.1.1_455.32.00_linux.run
--no-drm
--no-man-page
--override
--installpath
=
~/local
--librarypath
=
~/local/lib
--toolkitpath
=
~/local/cuda-11.1/
--toolkit
--silent
echo
"export LD_LIBRARY_PATH=
$LD_LIBRARY_PATH
:~/local/cuda-11.1/lib64/"
>>
~/.bashrc
echo
"export PATH=
$PATH
:~/local/cuda-11.1/bin/"
>>
~/.bashrc
source
~/.bashrc
tests/test_cuda_setup_evaluator.py
View file @
dd50382b
import
pytest
import
os
from
typing
import
List
...
...
@@ -16,6 +17,7 @@ HAPPY_PATH__LD_LIB_TEST_PATHS: List[tuple[str,str]] = [
(
f
"some/other/dir:dir/with/
{
CUDA_RUNTIME_LIB
}
:"
,
f
"dir/with/
{
CUDA_RUNTIME_LIB
}
"
),
(
f
"some/other/dir::dir/with/
{
CUDA_RUNTIME_LIB
}
"
,
f
"dir/with/
{
CUDA_RUNTIME_LIB
}
"
),
(
f
"dir/with/
{
CUDA_RUNTIME_LIB
}
:some/other/dir"
,
f
"dir/with/
{
CUDA_RUNTIME_LIB
}
"
),
(
f
"dir/with/
{
CUDA_RUNTIME_LIB
}
:other/dir/libcuda.so"
,
f
"dir/with/
{
CUDA_RUNTIME_LIB
}
"
),
]
...
...
@@ -64,3 +66,21 @@ def test_get_cuda_runtime_lib_path__non_existent_dir(capsys, tmp_path):
match
in
std_err
for
match
in
{
"WARNING"
,
"non-existent"
}
)
def
test_full_system
():
## this only tests the cuda version and not compute capability
ld_path
=
os
.
environ
[
'LD_LIBRARY_PATH'
]
paths
=
ld_path
.
split
(
':'
)
version
=
''
for
p
in
paths
:
if
'cuda'
in
p
:
idx
=
p
.
rfind
(
'cuda-'
)
version
=
p
[
idx
+
5
:
idx
+
5
+
4
].
replace
(
'/'
,
''
)
version
=
float
(
version
)
break
binary_name
=
evaluate_cuda_setup
()
binary_name
=
binary_name
.
replace
(
'libbitsandbytes_cuda'
,
''
)
assert
binary_name
.
startswith
(
str
(
version
).
replace
(
'.'
,
''
))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment