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.

parampack.py 6.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # -*- coding: utf-8 -*-
  2. # MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  3. #
  4. # Copyright (c) 2014-2020 Megvii Inc. All rights reserved.
  5. #
  6. # Unless required by applicable law or agreed to in writing,
  7. # software distributed under the License is distributed on an
  8. # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. import collections
  10. from typing import Callable, Iterable, Optional, Tuple
  11. import numpy as np
  12. from ..tensor_nn import Parameter, Tensor
  13. from .module import Module
  14. class ParamPack(Module):
  15. r"""Pack module's parameters by gathering their memory to continuous address.
  16. Using (device, dtype, requires_grad) as key, for example ('gpu0', float32, True),
  17. parameters with same key will be packed togather.
  18. It helps a lot for multimachine training by speeding up allreduce gradients.
  19. :param model: the module you want to pack parameters.
  20. :param nr_ignore_first: how many parameters will be unpacked at first.
  21. :param max_size_per_group: upper bound of packed parameters' size in MB.
  22. :param max_nr_params_per_group: upper bound of the number of parameters of each group.
  23. """
  24. def __init__(
  25. self,
  26. model: Module,
  27. nr_ignore_first: int = 8,
  28. max_size_per_group: int = 10,
  29. max_nr_params_per_group: int = 100,
  30. group_func: Callable = lambda name, param: 0,
  31. ):
  32. super().__init__()
  33. self._model = model
  34. self._nr_ignore_first = nr_ignore_first
  35. self._max_size_per_group = max_size_per_group
  36. self._max_nr_params_per_group = max_nr_params_per_group
  37. self._group_func = group_func
  38. self._grouped_params = []
  39. self._packed_params = []
  40. params = model.named_parameters()
  41. self._pack_params(params)
  42. def parameters(self, requires_grad: Optional[bool] = None) -> Iterable[Parameter]:
  43. for param in self._packed_params:
  44. if requires_grad is None or param.requires_grad == requires_grad:
  45. yield param
  46. def named_parameters(
  47. self, requires_grad: Optional[bool] = None
  48. ) -> Iterable[Tuple[str, Parameter]]:
  49. for idx, param in enumerate(self._packed_params):
  50. if requires_grad is None or param.requires_grad == requires_grad:
  51. yield "packed_param_" + str(idx), param
  52. def _pack_params(self, params: Iterable[Tuple[str, Parameter]]):
  53. groups = collections.defaultdict(list)
  54. ignored = 0
  55. param_id = 0
  56. for name, param in params:
  57. if self._nr_ignore_first > ignored:
  58. ignored += 1
  59. self._grouped_params.append([{"shape": param.shape, "id": param_id}])
  60. param.pack_group_key = self._group_func(name, param)
  61. self._packed_params.append(param)
  62. else:
  63. key = (
  64. param.dtype,
  65. param.device,
  66. param.requires_grad,
  67. self._group_func(name, param),
  68. )
  69. groups[key].append({"tensor": param, "id": param_id})
  70. param_id += 1
  71. for (dtype, device, requires_grad, group_key) in groups.keys():
  72. dtype_sz = np.dtype(dtype).itemsize
  73. align = device.mem_align
  74. if align < dtype_sz:
  75. align = 1
  76. else:
  77. assert align % dtype_sz == 0
  78. align //= dtype_sz
  79. group = groups[(dtype, device, requires_grad, group_key)]
  80. while group:
  81. aligned_pos = []
  82. offset = 0
  83. params = []
  84. idx = 0
  85. while idx < len(group):
  86. param = group[idx]
  87. assert param["tensor"].device == device
  88. padding = (align - (offset & (align - 1))) & (align - 1)
  89. offset += padding
  90. aligned_pos.append(offset)
  91. params.append(param)
  92. offset += int(np.prod(param["tensor"].shape))
  93. idx += 1
  94. if (
  95. offset * dtype_sz >= self._max_size_per_group * 1024 * 1024
  96. or idx >= self._max_nr_params_per_group
  97. ):
  98. break
  99. group = group[idx:]
  100. if idx == 1:
  101. # ignore param packs with only one item
  102. params[0]["tensor"].pack_group_key = group_key
  103. self._packed_params.append(params[0]["tensor"])
  104. self._grouped_params.append(
  105. [{"shape": params[0]["tensor"].shape, "id": params[0]["id"]}]
  106. )
  107. continue
  108. packed_value = np.zeros((offset,), dtype=dtype)
  109. for param, pos in zip(params, aligned_pos):
  110. val = param["tensor"].numpy()
  111. packed_value[pos : pos + val.size] = val.flatten()
  112. new_param = Parameter(
  113. value=packed_value,
  114. device=device,
  115. dtype=dtype,
  116. requires_grad=requires_grad,
  117. )
  118. new_param.pack_group_key = group_key
  119. self._packed_params.append(new_param)
  120. self._grouped_params.append(
  121. [{"shape": i["tensor"].shape, "id": i["id"]} for i in params]
  122. )
  123. def forward(self, *args, **kwargs):
  124. replace_param = dict()
  125. for i in range(len(self._packed_params)):
  126. packed_param = self._packed_params[i]
  127. grouped_params = self._grouped_params[i]
  128. if len(grouped_params) == 1:
  129. continue
  130. split = param_pack_split(
  131. packed_param._symvar, [i["shape"] for i in grouped_params]
  132. )
  133. split = [
  134. Parameter(Tensor(i, requires_grad=packed_param.requires_grad))
  135. for i in split
  136. ]
  137. for j in range(len(split)):
  138. replace_param[grouped_params[j]["id"]] = split[j]
  139. self._model.replace_param(replace_param, 0)
  140. return self._model.forward(*args, **kwargs)

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