You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

manifest.py 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #
  2. # \file generator.py
  3. #
  4. # \brief Generates the CUTLASS Library's instances
  5. #
  6. import enum
  7. import os.path
  8. import shutil
  9. from library import *
  10. from gemm_operation import *
  11. from conv2d_operation import *
  12. ###################################################################################################
  13. class EmitOperationKindLibrary:
  14. def __init__(self, generated_path, kind, args):
  15. self.generated_path = generated_path
  16. self.kind = kind
  17. self.args = args
  18. self.emitters = {
  19. OperationKind.Gemm: EmitGemmConfigurationLibrary
  20. , OperationKind.Conv2d: EmitConv2dConfigurationLibrary
  21. }
  22. self.configurations = [];
  23. self.header_template ="""
  24. /*
  25. Generated by manifest.py - Do not edit.
  26. */
  27. #include "cutlass/cutlass.h"
  28. #include "cutlass/library/library.h"
  29. #include "cutlass/library/manifest.h"
  30. namespace cutlass {
  31. namespace library {
  32. ///////////////////////////////////////////////////////////////////////////////////////////////////
  33. """
  34. self.entry_template = """
  35. //
  36. // Entry point to construct operations
  37. //
  38. void initialize_all_${operation_name}_operations(Manifest &manifest) {
  39. """
  40. self.configuration_prototype_template = "void initialize_${configuration_name}(Manifest &manifest);\n"
  41. self.configuration_template =" initialize_${configuration_name}(manifest);\n"
  42. self.epilogue_template ="""
  43. }
  44. ///////////////////////////////////////////////////////////////////////////////////////////////////
  45. } // namespace library
  46. } // namespace cutlass
  47. """
  48. #
  49. def __enter__(self):
  50. self.operation_path = os.path.join(self.generated_path, OperationKindNames[self.kind])
  51. os.mkdir(self.operation_path)
  52. self.top_level_path = os.path.join(self.operation_path, "all_%s_operations.cu" % OperationKindNames[self.kind])
  53. self.top_level_file = open(self.top_level_path, "w")
  54. self.top_level_file.write(self.header_template)
  55. self.source_files = [self.top_level_path,]
  56. return self
  57. #
  58. def emit(self, configuration_name, operations):
  59. with self.emitters[self.kind](self.operation_path, configuration_name) as configuration_emitter:
  60. for operation in operations:
  61. configuration_emitter.emit(operation)
  62. self.source_files.append(configuration_emitter.configuration_path)
  63. self.configurations.append(configuration_name)
  64. self.top_level_file.write(SubstituteTemplate(self.configuration_prototype_template, {'configuration_name': configuration_name} ))
  65. #
  66. def __exit__(self, exception_type, exception_value, traceback):
  67. self.top_level_file.write(SubstituteTemplate(self.entry_template, {'operation_name': OperationKindNames[self.kind]}))
  68. for configuration_name in self.configurations:
  69. self.top_level_file.write(SubstituteTemplate(self.configuration_template, {'configuration_name': configuration_name}))
  70. self.top_level_file.write(self.epilogue_template)
  71. self.top_level_file.close()
  72. ###################################################################################################
  73. ###################################################################################################
  74. class Options:
  75. def __init__(self):
  76. pass
  77. ###################################################################################################
  78. #
  79. class Manifest:
  80. #
  81. def __init__(self, args):
  82. self.operations = {}
  83. self.args = args
  84. architectures = args.architectures.split(';') if len(args.architectures) else ['50',]
  85. self.compute_capabilities = [int(x) for x in architectures]
  86. self.selected_kernels = []
  87. if args.operations == 'all':
  88. self.operations_enabled = []
  89. else:
  90. operations_list = [
  91. OperationKind.Gemm
  92. , OperationKind.Conv2d
  93. ]
  94. self.operations_enabled = [x for x in operations_list if OperationKindNames[x] in args.operations.split(',')]
  95. if args.kernels == 'all':
  96. self.kernel_names = []
  97. else:
  98. self.kernel_names = [x for x in args.kernels.split(',') if x != '']
  99. self.ignore_kernel_names = [x for x in args.ignore_kernels.split(',') if x != '']
  100. if args.kernel_filter_file is None:
  101. self.kernel_filter_list = []
  102. else:
  103. self.kernel_filter_list = self.get_kernel_filters(args.kernel_filter_file)
  104. self.operation_count = 0
  105. self.operations_by_name = {}
  106. self.top_level_prologue = '''
  107. #include "cutlass/library/library.h"
  108. #include "cutlass/library/manifest.h"
  109. namespace cutlass {
  110. namespace library {
  111. ${prototypes}
  112. void initialize_all(Manifest &manifest) {
  113. '''
  114. self.top_level_reserve = ' manifest.reserve(${operation_count});\n\n'
  115. self.top_level_epilogue = '''
  116. }
  117. } // namespace library
  118. } // namespace cutlass
  119. '''
  120. def get_kernel_filters (self, kernelListFile):
  121. if os.path.isfile(kernelListFile):
  122. with open(kernelListFile, 'r') as fileReader:
  123. lines = [line.rstrip() for line in fileReader if not line.startswith("#")]
  124. lines = [re.compile(line) for line in lines if line]
  125. return lines
  126. else:
  127. return []
  128. def filter_out_kernels(self, kernel_name, kernel_filter_list):
  129. for kernel_filter_re in kernel_filter_list:
  130. if kernel_filter_re.search(kernel_name) is not None:
  131. return True
  132. return False
  133. #
  134. def _filter_string_matches(self, filter_string, haystack):
  135. ''' Returns true if all substrings appear in the haystack in order'''
  136. substrings = filter_string.split('*')
  137. for sub in substrings:
  138. idx = haystack.find(sub)
  139. if idx < 0:
  140. return False
  141. haystack = haystack[idx + len(sub):]
  142. return True
  143. #
  144. def filter(self, operation):
  145. ''' Filtering operations based on various criteria'''
  146. # filter based on compute capability
  147. enabled = False
  148. for cc in self.compute_capabilities:
  149. if cc >= operation.tile_description.minimum_compute_capability and \
  150. cc <= operation.tile_description.maximum_compute_capability:
  151. enabled = True
  152. break
  153. if not enabled:
  154. return False
  155. if len(self.operations_enabled) and not operation.operation_kind in self.operations_enabled:
  156. return False
  157. # eliminate duplicates
  158. if operation.procedural_name() in self.operations_by_name.keys():
  159. return False
  160. # Filter based on list of valid substrings
  161. if len(self.kernel_names):
  162. name = operation.procedural_name()
  163. enabled = False
  164. # compare against the include list
  165. for name_substr in self.kernel_names:
  166. if self._filter_string_matches(name_substr, name):
  167. enabled = True
  168. break
  169. # compare against the exclude list
  170. for name_substr in self.ignore_kernel_names:
  171. if self._filter_string_matches(name_substr, name):
  172. enabled = False
  173. break
  174. if len(self.kernel_filter_list) > 0:
  175. enabled = False
  176. if self.filter_out_kernels(operation.procedural_name(), self.kernel_filter_list):
  177. enabled = True
  178. # todo: filter based on compute data type
  179. return enabled
  180. #
  181. #
  182. def append(self, operation):
  183. '''
  184. Inserts the operation.
  185. operation_kind -> configuration_name -> []
  186. '''
  187. if self.filter(operation):
  188. self.selected_kernels.append(operation.procedural_name())
  189. self.operations_by_name[operation.procedural_name()] = operation
  190. # add the configuration
  191. configuration_name = operation.configuration_name()
  192. if operation.operation_kind not in self.operations.keys():
  193. self.operations[operation.operation_kind] = {}
  194. if configuration_name not in self.operations[operation.operation_kind].keys():
  195. self.operations[operation.operation_kind][configuration_name] = []
  196. self.operations[operation.operation_kind][configuration_name].append(operation)
  197. self.operation_count += 1
  198. #
  199. #
  200. def emit(self, target = GeneratorTarget.Library):
  201. operation_emitters = {
  202. GeneratorTarget.Library: EmitOperationKindLibrary
  203. }
  204. generated_path = os.path.join(self.args.curr_build_dir, 'generated')
  205. # create generated/
  206. if os.path.exists(generated_path):
  207. shutil.rmtree(generated_path)
  208. os.mkdir(generated_path)
  209. source_files = []
  210. top_level_path = os.path.join(generated_path, 'initialize_all.cpp')
  211. with open(top_level_path, 'w') as top_level_file:
  212. if target == GeneratorTarget.Library:
  213. source_files.append(top_level_path)
  214. prototypes = []
  215. for operation_kind, configurations in self.operations.items():
  216. prototypes.append(SubstituteTemplate(
  217. "void initialize_all_${operation_kind}_operations(Manifest &manifest);",
  218. {'operation_kind': OperationKindNames[operation_kind]}))
  219. top_level_file.write(SubstituteTemplate(self.top_level_prologue,
  220. {'prototypes': "\n".join(prototypes)}))
  221. top_level_file.write(SubstituteTemplate(
  222. self.top_level_reserve, {'operation_count': str(self.operation_count)}))
  223. # for each operation kind, emit initializer for all configurations
  224. for operation_kind, configurations in self.operations.items():
  225. with operation_emitters[target](generated_path, operation_kind, self.args) as operation_kind_emitter:
  226. for configuration_name, operations in configurations.items():
  227. operation_kind_emitter.emit(configuration_name, operations)
  228. source_files += operation_kind_emitter.source_files
  229. top_level_file.write(SubstituteTemplate(
  230. " initialize_all_${operation_kind}_operations(manifest);\n",
  231. {'operation_kind': OperationKindNames[operation_kind]}))
  232. top_level_file.write(self.top_level_epilogue)
  233. # write the manifest.cmake file containing paths from all targets
  234. manifest_path = os.path.join(generated_path, "manifest.cmake")
  235. with open(manifest_path, "w") as manifest_file:
  236. target_name = 'cutlass_library_objs'
  237. target_text = SubstituteTemplate("""cutlass_target_sources(
  238. ${target_name}
  239. BATCH_SOURCES ON
  240. PRIVATE
  241. """, { 'target_name': target_name})
  242. manifest_file.write(target_text)
  243. for source_file in source_files:
  244. manifest_file.write(" %s\n" % str(source_file.replace('\\', '/')))
  245. manifest_file.write(")")
  246. #
  247. ###################################################################################################

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台