real_accelerator.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # Copyright (c) Microsoft Corporation.
  2. # SPDX-License-Identifier: Apache-2.0
  3. # DeepSpeed Team
  4. import os
  5. try:
  6. # Importing logger currently requires that torch is installed, hence the try...except
  7. # TODO: Remove logger dependency on torch.
  8. from deepspeed.utils import logger as accel_logger
  9. except ImportError as e:
  10. accel_logger = None
  11. try:
  12. from accelerator.abstract_accelerator import DeepSpeedAccelerator as dsa1
  13. except ImportError as e:
  14. dsa1 = None
  15. try:
  16. from deepspeed.accelerator.abstract_accelerator import DeepSpeedAccelerator as dsa2
  17. except ImportError as e:
  18. dsa2 = None
  19. ds_accelerator = None
  20. def _validate_accelerator(accel_obj):
  21. # because abstract_accelerator has different path during
  22. # build time (accelerator.abstract_accelerator)
  23. # and run time (deepspeed.accelerator.abstract_accelerator)
  24. # and extension would import the
  25. # run time abstract_accelerator/DeepSpeedAccelerator as its base
  26. # class, so we need to compare accel_obj with both base class.
  27. # if accel_obj is instance of DeepSpeedAccelerator in one of
  28. # accelerator.abstractor_accelerator
  29. # or deepspeed.accelerator.abstract_accelerator, consider accel_obj
  30. # is a conforming object
  31. if not ((dsa1 != None and isinstance(accel_obj, dsa1)) or (dsa2 != None and isinstance(accel_obj, dsa2))):
  32. raise AssertionError(f"{accel_obj.__class__.__name__} accelerator is not subclass of DeepSpeedAccelerator")
  33. # TODO: turn off is_available test since this breaks tests
  34. # assert accel_obj.is_available(), \
  35. # f'{accel_obj.__class__.__name__} accelerator fails is_available() test'
  36. def get_accelerator():
  37. global ds_accelerator
  38. if ds_accelerator is not None:
  39. return ds_accelerator
  40. accelerator_name = None
  41. ds_set_method = None
  42. # 1. Detect whether there is override of DeepSpeed accelerators from environment variable.
  43. DS_ACCELERATOR_LIST = ['cuda', 'cpu', 'xpu', 'npu', 'mps']
  44. if "DS_ACCELERATOR" in os.environ.keys():
  45. accelerator_name = os.environ["DS_ACCELERATOR"]
  46. if accelerator_name == "xpu":
  47. try:
  48. from intel_extension_for_deepspeed import XPU_Accelerator # noqa: F401
  49. except ImportError as e:
  50. raise ValueError(
  51. f"XPU_Accelerator requires intel_extension_for_deepspeed, which is not installed on this system.")
  52. elif accelerator_name == "cpu":
  53. try:
  54. import intel_extension_for_pytorch # noqa: F401
  55. except ImportError as e:
  56. raise ValueError(
  57. f"CPU_Accelerator requires intel_extension_for_pytorch, which is not installed on this system.")
  58. elif accelerator_name == "npu":
  59. try:
  60. import torch_npu # noqa: F401
  61. except ImportError as e:
  62. raise ValueError(f"NPU_Accelerator requires torch_npu, which is not installed on this system.")
  63. pass
  64. elif accelerator_name == "mps":
  65. try:
  66. import torch.mps
  67. # should use torch.mps.is_available() if it exists someday but this is used as proxy
  68. torch.mps.current_allocated_memory()
  69. except (RuntimeError, ImportError) as e:
  70. raise ValueError(f"MPS_Accelerator requires torch.mps, which is not installed on this system.")
  71. elif accelerator_name == "cuda":
  72. pass
  73. else:
  74. raise ValueError(
  75. f'DS_ACCELERATOR must be one of {DS_ACCELERATOR_LIST}. Value "{accelerator_name}" is not supported')
  76. ds_set_method = "override"
  77. # 2. If no override, detect which accelerator to use automatically
  78. if accelerator_name == None:
  79. # We need a way to choose among different accelerator types.
  80. # Currently we detect which accelerator extension is installed
  81. # in the environment and use it if the installing answer is True.
  82. # An alternative might be detect whether CUDA device is installed on
  83. # the system but this comes with two pitfalls:
  84. # 1. the system may not have torch pre-installed, so
  85. # get_accelerator().is_available() may not work.
  86. # 2. Some scenario like install on login node (without CUDA device)
  87. # and run on compute node (with CUDA device) may cause mismatch
  88. # between installation time and runtime.
  89. try:
  90. from intel_extension_for_deepspeed import XPU_Accelerator # noqa: F401,F811
  91. accelerator_name = "xpu"
  92. except ImportError as e:
  93. pass
  94. if accelerator_name == None:
  95. try:
  96. import intel_extension_for_pytorch # noqa: F401,F811
  97. accelerator_name = "cpu"
  98. except ImportError as e:
  99. pass
  100. if accelerator_name == None:
  101. try:
  102. import torch_npu # noqa: F401,F811
  103. accelerator_name = "npu"
  104. except ImportError as e:
  105. pass
  106. if accelerator_name == None:
  107. try:
  108. import torch.mps
  109. # should use torch.mps.is_available() if it exists someday but this is used as proxy
  110. torch.mps.current_allocated_memory()
  111. accelerator_name = "mps"
  112. except (RuntimeError, ImportError) as e:
  113. pass
  114. if accelerator_name == None:
  115. accelerator_name = "cuda"
  116. ds_set_method = "auto detect"
  117. # 3. Set ds_accelerator accordingly
  118. if accelerator_name == "cuda":
  119. from .cuda_accelerator import CUDA_Accelerator
  120. ds_accelerator = CUDA_Accelerator()
  121. elif accelerator_name == "cpu":
  122. from .cpu_accelerator import CPU_Accelerator
  123. ds_accelerator = CPU_Accelerator()
  124. elif accelerator_name == "xpu":
  125. # XPU_Accelerator is already imported in detection stage
  126. ds_accelerator = XPU_Accelerator()
  127. elif accelerator_name == "npu":
  128. from .npu_accelerator import NPU_Accelerator
  129. ds_accelerator = NPU_Accelerator()
  130. elif accelerator_name == "mps":
  131. from .mps_accelerator import MPS_Accelerator
  132. ds_accelerator = MPS_Accelerator()
  133. _validate_accelerator(ds_accelerator)
  134. if accel_logger is not None:
  135. accel_logger.info(f"Setting ds_accelerator to {ds_accelerator._name} ({ds_set_method})")
  136. return ds_accelerator
  137. def set_accelerator(accel_obj):
  138. global ds_accelerator
  139. _validate_accelerator(accel_obj)
  140. if accel_logger is not None:
  141. accel_logger.info(f"Setting ds_accelerator to {accel_obj._name} (model specified)")
  142. ds_accelerator = accel_obj
  143. """
  144. -----------[code] test_get.py -----------
  145. from deepspeed.accelerator import get_accelerator
  146. my_accelerator = get_accelerator()
  147. logger.info(f'{my_accelerator._name=}')
  148. logger.info(f'{my_accelerator._communication_backend=}')
  149. logger.info(f'{my_accelerator.HalfTensor().device=}')
  150. logger.info(f'{my_accelerator.total_memory()=}')
  151. -----------[code] test_get.py -----------
  152. ---[output] python test_get.py---------
  153. my_accelerator.name()='cuda'
  154. my_accelerator.communication_backend='nccl'
  155. my_accelerator.HalfTensor().device=device(type='cuda', index=0)
  156. my_accelerator.total_memory()=34089730048
  157. ---[output] python test_get.py---------
  158. **************************************************************************
  159. -----------[code] test_set.py -----------
  160. from deepspeed.accelerator.cuda_accelerator import CUDA_Accelerator
  161. cu_accel = CUDA_Accelerator()
  162. logger.info(f'{id(cu_accel)=}')
  163. from deepspeed.accelerator import set_accelerator, get_accelerator
  164. set_accelerator(cu_accel)
  165. my_accelerator = get_accelerator()
  166. logger.info(f'{id(my_accelerator)=}')
  167. logger.info(f'{my_accelerator._name=}')
  168. logger.info(f'{my_accelerator._communication_backend=}')
  169. logger.info(f'{my_accelerator.HalfTensor().device=}')
  170. logger.info(f'{my_accelerator.total_memory()=}')
  171. -----------[code] test_set.py -----------
  172. ---[output] python test_set.py---------
  173. id(cu_accel)=139648165478304
  174. my_accelerator=<deepspeed.accelerator.cuda_accelerator.CUDA_Accelerator object at 0x7f025f4bffa0>
  175. my_accelerator.name='cuda'
  176. my_accelerator.communication_backend='nccl'
  177. my_accelerator.HalfTensor().device=device(type='cuda', index=0)
  178. my_accelerator.total_memory()=34089730048
  179. ---[output] python test_set.py---------
  180. """