Advertisement
Guest User

Untitled

a guest
Oct 26th, 2022
731
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.29 KB | None | 0 0
  1. """
  2. extract factors the build is dependent on:
  3. [X] compute capability
  4. [ ] TODO: Q - What if we have multiple GPUs of different makes?
  5. - CUDA version
  6. - Software:
  7. - CPU-only: only CPU quantization functions (no optimizer, no matrix multipl)
  8. - CuBLAS-LT: full-build 8-bit optimizer
  9. - no CuBLAS-LT: no 8-bit matrix multiplication (`nomatmul`)
  10.  
  11. evaluation:
  12. - if paths faulty, return meaningful error
  13. - else:
  14. - determine CUDA version
  15. - determine capabilities
  16. - based on that set the default path
  17. """
  18.  
  19. import ctypes
  20.  
  21. from .paths import determine_cuda_runtime_lib_path
  22. from bitsandbytes.cextension import CUDASetup
  23.  
  24.  
  25. def check_cuda_result(cuda, result_val):
  26. # 3. Check for CUDA errors
  27. if result_val != 0:
  28. error_str = ctypes.c_char_p()
  29. cuda.cuGetErrorString(result_val, ctypes.byref(error_str))
  30. CUDASetup.get_instance.add_log_entry(f"CUDA exception! Error code: {error_str.value.decode()}")
  31.  
  32. def get_cuda_version(cuda, cudart_path):
  33. # https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART____VERSION.html#group__CUDART____VERSION
  34. try:
  35. cudart = ctypes.CDLL(cudart_path)
  36. except OSError:
  37. CUDASetup.get_instance.add_log_entry(f'ERROR: libcudart.so could not be read from path: {cudart_path}!')
  38. return None
  39.  
  40. version = ctypes.c_int()
  41. check_cuda_result(cuda, cudart.cudaRuntimeGetVersion(ctypes.byref(version)))
  42. version = int(version.value)
  43. major = version//1000
  44. minor = (version-(major*1000))//10
  45.  
  46. if major < 11:
  47. CUDASetup.get_instance().add_log_entry('CUDA SETUP: CUDA version lower than 11 are currenlty not supported for LLM.int8(). You will be only to use 8-bit optimizers and quantization routines!!')
  48.  
  49. return f'{major}{minor}'
  50.  
  51.  
  52. def get_cuda_lib_handle():
  53. # 1. find libcuda.so library (GPU driver) (/usr/lib)
  54. try:
  55. cuda = ctypes.CDLL("libcuda.so")
  56. except OSError:
  57. CUDA_RUNTIME_LIB.get_instance().add_log_entry('CUDA SETUP: WARNING! libcuda.so not found! Do you have a CUDA driver installed? If you are on a cluster, make sure you are on a CUDA machine!')
  58. return None
  59. check_cuda_result(cuda, cuda.cuInit(0))
  60.  
  61. return cuda
  62.  
  63.  
  64. def get_compute_capabilities(cuda):
  65. """
  66. 1. find libcuda.so library (GPU driver) (/usr/lib)
  67. init_device -> init variables -> call function by reference
  68. 2. call extern C function to determine CC
  69. (https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__DEVICE__DEPRECATED.html)
  70. 3. Check for CUDA errors
  71. https://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime-api
  72. # bits taken from https://gist.github.com/f0k/63a664160d016a491b2cbea15913d549
  73. """
  74.  
  75.  
  76. nGpus = ctypes.c_int()
  77. cc_major = ctypes.c_int()
  78. cc_minor = ctypes.c_int()
  79.  
  80. device = ctypes.c_int()
  81.  
  82. check_cuda_result(cuda, cuda.cuDeviceGetCount(ctypes.byref(nGpus)))
  83. ccs = []
  84. for i in range(nGpus.value):
  85. check_cuda_result(cuda, cuda.cuDeviceGet(ctypes.byref(device), i))
  86. ref_major = ctypes.byref(cc_major)
  87. ref_minor = ctypes.byref(cc_minor)
  88. # 2. call extern C function to determine CC
  89. check_cuda_result(
  90. cuda, cuda.cuDeviceComputeCapability(ref_major, ref_minor, device)
  91. )
  92. ccs.append(f"{cc_major.value}.{cc_minor.value}")
  93.  
  94. return ccs
  95.  
  96.  
  97. # def get_compute_capability()-> Union[List[str, ...], None]: # FIXME: error
  98. def get_compute_capability(cuda):
  99. """
  100. Extracts the highest compute capbility from all available GPUs, as compute
  101. capabilities are downwards compatible. If no GPUs are detected, it returns
  102. None.
  103. """
  104. ccs = get_compute_capabilities(cuda)
  105. if ccs:
  106. # TODO: handle different compute capabilities; for now, take the max
  107. return ccs[-1]
  108. return None
  109.  
  110.  
  111. def evaluate_cuda_setup():
  112. return "libbitsandbytes_cuda116.dll"
  113. # we remove this for now and see how things go
  114. #print('')
  115. #print('='*35 + 'BUG REPORT' + '='*35)
  116. #print('Welcome to bitsandbytes. For bug reports, please submit your error trace to: https://github.com/TimDettmers/bitsandbytes/issues')
  117. #print('For effortless bug reporting copy-paste your error into this form: https://docs.google.com/forms/d/e/1FAIpQLScPB8emS3Thkp66nvqwmjTEgxp8Y9ufuWTzFyr9kJ5AoI47dQ/viewform?usp=sf_link')
  118. #print('='*80)
  119. #if not torch.cuda.is_available():
  120. #print('No GPU detected. Loading CPU library...')
  121. #return binary_name
  122.  
  123. binary_name = "libbitsandbytes_cuda116.dll"
  124.  
  125. cuda_setup = CUDASetup.get_instance()
  126. cudart_path = determine_cuda_runtime_lib_path()
  127. if cudart_path is None:
  128. cuda_setup.add_log_entry("WARNING: No libcudart.so found! Install CUDA or the cudatoolkit package (anaconda)!", is_warning=True)
  129. return binary_name
  130.  
  131. cuda_setup.add_log_entry((f"CUDA SETUP: CUDA runtime path found: {cudart_path}"))
  132. cuda = get_cuda_lib_handle()
  133. cc = get_compute_capability(cuda)
  134. cuda_setup.add_log_entry(f"CUDA SETUP: Highest compute capability among GPUs detected: {cc}")
  135. cuda_version_string = get_cuda_version(cuda, cudart_path)
  136.  
  137.  
  138. if cc == '':
  139. cuda_setup.add_log_entry("WARNING: No GPU detected! Check your CUDA paths. Processing to load CPU-only library...", is_warning=True)
  140. return binary_name
  141.  
  142. # 7.5 is the minimum CC vor cublaslt
  143. has_cublaslt = cc in ["7.5", "8.0", "8.6"]
  144.  
  145. # TODO:
  146. # (1) CUDA missing cases (no CUDA installed by CUDA driver (nvidia-smi accessible)
  147. # (2) Multiple CUDA versions installed
  148.  
  149. # we use ls -l instead of nvcc to determine the cuda version
  150. # since most installations will have the libcudart.so installed, but not the compiler
  151. cuda_setup.add_log_entry(f'CUDA SETUP: Detected CUDA version {cuda_version_string}')
  152.  
  153. def get_binary_name():
  154. "if not has_cublaslt (CC < 7.5), then we have to choose _nocublaslt.so"
  155. bin_base_name = "libbitsandbytes_cuda"
  156. if has_cublaslt:
  157. return f"{bin_base_name}{cuda_version_string}.so"
  158. else:
  159. return f"{bin_base_name}{cuda_version_string}_nocublaslt.so"
  160.  
  161. binary_name = get_binary_name()
  162.  
  163. return binary_name, cudart_path, cuda, cc, cuda_version_string
  164.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement