ශුන්ය-ඩීපීමතක ප්රශස්තිකරණය

මෙයකඩදාසි වල හඳුන්වා දුන් ශුන්ය-ඩීපී ක්රියාත්මක කිරීමකි ශුන්ය: පුහුණුව සඳහා මතක ප්රශස්තිකරණය ට්රිලියනයක් පරාමිති ආකෘති,

එයප්රශස්තිකරණ තත්වයේ, ශ්රේණියේ සහ පරාමිතීන් බහු උපාංග/නෝඩ් වලට තබා ගනී. එය මුල් ආකෘතියට මතක පරිභෝජනය අඩු කරයි, පරාමිති ගණන කොතැනද, කැබලි ගණන ද , පරාමිතියකට ප්රශස්තිකරණ බයිට් ගණන. බිට් 16-නිරවද්යතාව උපකල්පනය කරන පරාමිතිය සහ ශ්රේණියේ මතකය; එනම් පරාමිතියට බයිට් 2 ක් සහ අනුක්රමික ය. සඳහා ආදම් ප්රශස්තකරණය එය පරාමිතීන්ගේ පිටපතක් සහ fp32 හි පරාමිතියකට අවස්ථා දෙකක් පවත්වා ගෙන යන බැවිනි.

ශුන්ය-ඩීපීහි සන්නිවේදන පරිමාව වේ . සංසන්දනය සඳහා දත්ත-සමාන්තර පුහුණුව සන්නිවේදන පරිමාවක් ඇත.

මෙයනම් කර ඇතත් Zero3 , අප ක්රියාත්මක කර ඇත්තේ එහි ශුන්ය-ඩීපී කොටස පමණක් මිස අවශේෂ මතක පරිභෝජනය ඉලක්ක කරන Zero-R මතක ප්රශස්තිකරණයන් නොවේ. පිටත ක්රියාත්මක කිරීම සඳහා පුහුණුව සඳහා සහාය වන්නේ පරාමිතීන්ගේ උප කුලකයක් පමණි.

මෙමක්රියාත්මක කිරීම Fairscale FSDPවිසින් දේවානුභාවයෙන්.

ZERO-DP මතක ප්රශස්තිකරණය භාවිතා කරමින් GPT Neox මනාව සකස් කිරීම සඳහා ස්ක්රිප්ට් එකක් මෙන්න .

32import functools
33from typing import List, Optional, Tuple
34
35import torch
36import torch.distributed as dist
37from torch import nn

Zero3ස්ථරය

ආකෘතියේසෑම ස්ථරයක්ම (හෝ අනුයාත ස්ථර කිහිපයක එකතුවක්) මෙම මොඩියුලය තුළ ඔතා තිබිය යුතුය.

40class Zero3Layer(nn.Module):

සෑමකොටසක්ම පරාමිතීන් chunk ලැයිස්තුවේ තබා ගනී. පුහුණු කළ හැකි පරාමිතීන් සඳහා chunk[0] chunk[1] වන අතර ස්ථාවර පරාමිතීන් සඳහා වේ.

49    chunk: List[nn.Parameter]

chunk ලැයිස්තුවේ ඇති කුට්ටි වල ප්රමාණය මෙයයි.

51    chunk_size: List[int]

පළමුකුට්ටිය පුහුණු කළ හැකි පරාමිතීන් සඳහා වේ.

53    TRAINING_PARAMS_IDX = 0

පුහුණුකළ හැකි සහ ස්ථාවර පරාමිතීන් ලෙස ලැයිස්තු වලට බෙදී ඇති පරාමිති ලැයිස්තුව මෙයයි.

56    param_refs: List[List[nn.Parameter]]

පරාමිතීන්පිහාටු කිරීමට CUDA ධාරාව

59    fetch_stream: Optional[torch.cuda.Stream]

උපස්ථ/සමුච්චයඵලය අනුක්රමික කිරීමට CDA ඇළ

61    backup_stream: Optional[torch.cuda.Stream]

මෙමස්ථරයට පෙර ස්ථර ලැයිස්තුව

63    prev_layer: List['Zero3Layer']

මෙමස්ථරයට පසුව ස්ථර ලැයිස්තුව

65    next_layer: List['Zero3Layer']

වත්මන්ස්ථරයේ පිහිටීම; ලඝු-සටහන් නිදොස්කරණය සඳහා මෙය භාවිතා කරයි

67    layer_idx: int

පරාමිතීන්ලබා ගෙන තිබේද

70    is_fetched: bool

ස්ථරයේඋපාංගය

73    device: torch.device

ස්ථරයේදත්ත වර්ගය

75    dtype: torch.dtype

එවියයුතු මොඩියුලය

77    module: nn.Module

නෝඩ්/උපාංගගණන දත්ත හරහා තියුණු වේ

79    world_size: int
  • module ඔතා ගත යුතු මොඩියුලය.
  • rank වත්මන් නෝඩයේ නිලය.
  • world_size දත්ත හරහා තියුණු කර ඇති නෝඩ්/උපාංග ගණන.
  • device ස්ථරයේ උපාංගය.
  • dtype ස්ථරයේ දත්ත වර්ගය.
81    def __init__(self, module: nn.Module, rank: int, world_size: int, device: torch.device, dtype: torch.dtype):
89        super().__init__()

ගුණාංගආරම්භ කරන්න

92        self.device = device
93        self.dtype = dtype
94        self.module = module
95        self.prev_layer = []
96        self.next_layer = []
97        self.is_fetched = False
98        self.world_size = world_size
99        self.layer_idx = -1
100        self.fetch_stream = None
101        self.backup_stream = None
102
103        with torch.no_grad():

ස්ථරයේසියලු පරාමිතීන් එකතු කරන්න

105            all_param_refs = [p for p in self.parameters()]

පරාමිතීන්ගේහැඩය ගබඩා කර තබන්න, මන්ද ඒවා ප්රතිනිර්මාණය කිරීමට අපට පසුව අවශ්ය වේ

108            for p in all_param_refs:
109                p._orig_shape = p.shape

සියලුමපරාමිතීන් එකම වර්ගයේ තිබිය යුතුය

112            for p in all_param_refs:
113                assert p.dtype == dtype, "All parameters should have same dtype"

පුහුණුකළ හැකි සහ ස්ථාවර ලෙස වෙනම පරාමිතීන්

116            self.param_refs = [[p for p in all_param_refs if p.requires_grad],
117                               [p for p in all_param_refs if not p.requires_grad]]
118            del all_param_refs

මෙම rank = 0 නෝඩය එක් එක් උපාංගය/නෝඩය ගබඩා කළ යුතු ප්රමාණය ගණනය කරනු ඇත, ඒ අනුව පරාමිතීන් බෙදා හරිනු ඇත.

122            if rank == 0:

ඒකාබද්ධකිරීම සහ පෑඩ් පුහුණු කළ හැකි (merged_params[0] ) සහ ස්ථාවර (merged_params[1] ) පරාමිතීන්

124                merged_params = [self._merge_and_pad_params(ps) for ps in self.param_refs]

පුහුණුකළ හැකි සහ ස්ථාවර පරාම් ප්රමාණ ගණනය කරන්න

126                self.chunk_size = [(len(p) // world_size if p is not None else 0) for p in merged_params]

ප්රමාණවිකාශනය කරන්න

128                dist.broadcast(torch.tensor(self.chunk_size, device=device), src=0)
129            else:

ප්රමාණලබා ගැනීම සඳහා හිස් ටෙන්සරයක් සාදන්න

131                chunk_size = torch.tensor([0, 0], device=device)

ප්රමාණලබා ගන්න

133                dist.broadcast(chunk_size, src=0)
134                self.chunk_size = chunk_size.tolist()

පුහුණුකළ හැකි (self.chunk[0] ) සහ ස්ථාවර (self.chunk[1] ) පරාමිතීන් සඳහා වත්මන් උපාංගයේ/නෝඩයේ ගබඩා කිරීම සඳහා පරාමිතීන් සාදන්න

138            self.chunk = [nn.Parameter(self._empty((s,)), requires_grad=i == self.TRAINING_PARAMS_IDX)
139                          for i, s in enumerate(self.chunk_size)]

පුහුණුකළ හැකි සහ ස්ථාවර පරාමිතීන් ඒකාබද්ධ කිරීම සඳහා හිස් ටෙන්සරයක්

142            chunk = self._empty((sum(self.chunk_size),))
143
144            if rank == 0:

පුහුණුකළ හැකි සහ ස්ථාවර පරාම් දෙකම සංයුක්ත කරන්න

146                all_params = torch.cat([p.view(world_size, -1) for p in merged_params], dim=-1).view(-1)
147                del merged_params

සියලුමනෝඩ්/උපාංග වෙත ඒවා විසුරුවා හරින්න

150                dist.scatter(chunk, list(all_params.split(sum(self.chunk_size))))
151                del all_params
152            else:

පරාමිතීන්ලබා ගන්න

154                dist.scatter(chunk)

කුට්ටියදත්ත එකතු කරන්න

157            chunk = chunk.split(self.chunk_size)
158            for i, c in enumerate(chunk):
159                self.chunk[i].data[:] = c
160            del chunk

සාමාන්යපරාමිතීන් පිරිසිදු කරන්න

163            self._cleanup_params()

පසුගාමීකොක්කක් එක් කරන්න. මොඩියුලයට සාපේක්ෂව අනුක්රමික ගණනය කළ විට මෙය කැඳවනු ලැබේ.

166            self._backward_hook_ref = self.register_full_backward_hook(self._backward_hook)  # type: ignore

සියලුපරාමිතීන් ඒකාබද්ධ කර එය බෙදිය හැකි වන පරිදි පෑඩ් කරන්න world_size .

168    def _merge_and_pad_params(self, params: List[nn.Parameter]) -> torch.Tensor:

මුළුපරාමිතීන් ගණන

173        size = sum(p.shape.numel() for p in params)

එයබෙදිය නොහැකි නම් world_size , එය පෑඩ් කරන්න

176        if size % self.world_size != 0:
177            padding_fixed = self.world_size - (size % self.world_size)

එසේනොමැති නම්, පෑඩ් කිරීමට අවශ්ය නැත

179        else:
180            padding_fixed = 0

හිස්පුරවන tensor සාදන්න

182        padding = self._empty((padding_fixed,))

සියලුමපරාමිතීන් සංයුක්ත කර එය පෑඩ් කරන්න

184        return torch.cat([p.view(-1) for p in params] + [padding], dim=0)

පරාමිතීන්ගේපුහුණු කළ හැකි කූඩු/මඩු ලබා ගන්න.

වත්මන්නෝඩයේ ප්රශස්තකරණය වෙත අප යන්නේ මෙයයි.

186    def get_trainable_chunk(self) -> List[nn.Parameter]:

පුහුණුකළ හැකි පරාමිතීන් නොමැති නම් ආපසු සහ හිස් ලැයිස්තුව

193        if len(self.chunk[self.TRAINING_PARAMS_IDX]) == 0:
194            return []

පුහුණුකළ හැකි කුට්ටිය ලැයිස්තුවක් ලෙස ආපසු එවන්න

197        return [self.chunk[self.TRAINING_PARAMS_IDX]]

දීඇති හැඩයේ හිස් ටෙන්සරයක් සාදන්න.

199    def _empty(self, shape: Tuple[int, ...]) -> torch.Tensor:
203        return torch.empty(shape, device=self.device, dtype=self.dtype)

පරාමිතිදත්ත පිරිසිදු කරන්න

මෙයස්ථර පරාමිතීන් විසින් භාවිතා කරන සියලුම මතකය මුදා හරිනු ඇත.

205    @torch.no_grad()
206    def _cleanup_params(self):

පරාමිතීන්ලබා ගත නොහැකි බව දැක්වීමට ධජය සකසන්න

214        self.is_fetched = False

සියලුපරාමිතීන් හරහා නැවත

217        for ps in self.param_refs:
218            for p in ps:

නවමෙහෙයුම් වලට පෙර පරාමිතීන්ගේ මෙහෙයුම් සම්පූර්ණ වන තෙක් රැඳී සිටින්න

220                p.data.record_stream(torch.cuda.current_stream())

පරාමිතියවෙනත් කිසිවක් සමඟ ගබඩා බෙදා නොගන්නා බවට වග බලා ගන්න පරීක්ෂා කරන්න

222                assert p.data.storage_offset() == 0, "The tensor is not the sole occupant of the storage."

ගබඩාවවෙනස් කරන්න . මෙය පරාමිතිය භාවිතා කරන මතකය මුදා හරිනු ඇත.

ස්වයංක්‍රීයප්‍රස්තාරය ඒ පිළිබඳව සඳහනක් තබා ඇති බැවින් සැකසුම මතකය මුදා p.data නොහරිනු ඇත.

226                p.data.storage().resize_(0)  # This is what actually clears the memory

පරාමිතියටශ්රේණියේ දත්ත නොමැති බවට වග බලා ගන්න

228                assert p.grad is None, 'Gradients should be None'

සියලුකැබලි වලින් පරාමිතීන් ලබා ගන්න

මෙයසියලු නෝඩ් වලින් සියලු පරාමිති දත්ත ලබා ගන්නා අතර එක් එක් නෝඩයේ පරාමිතීන් නැවත ගොඩනඟනු ඇත.

230    @torch.no_grad()
231    def fetch_params(self):

මඟහැරීම දැනටමත් ලැබී ඇත

239        if self.is_fetched:
240            return

ධජයසකසන්න

243        self.is_fetched = True
ලබා

ගැනීමට හෝ බෙදා ගැනීමට කිසිවක් නොමැති නම් මඟ හරින්න.

246        if sum(self.chunk_size) == 0:
247            return

සියලුකැබලි වලින් පරාමිතීන් ලබා fetch_stream ගැනීමට භාවිතා කරන්න

250        with torch.cuda.stream(self.fetch_stream):

පරාමිතීන්ලබා ගැනීම සඳහා හිස් ටෙන්සරයක් සාදන්න

252            buffer = self._empty((self.world_size * sum(self.chunk_size),))

අඛණ්ඩබෆරය නෝඩ් ගණනට බෙදන්න. මෙම බෙදීම් `බෆර්' පිළිබඳ අදහස් වේ.

254            buffers = list(buffer.split(sum(self.chunk_size)))

පුහුණුකළ හැකි සහ ස්ථාවර කුට්ටි දෙකම සංයුක්ත කරන්න

257            chunk = torch.cat(self.chunk, dim=0)

සියලුමනෝඩ්/උපාංග වලින් පරාමිතීන් එක්රැස් කරන්න

260            dist.all_gather(buffers, chunk)

රැස්කරන ලද පරාමිතීන් පුහුණු කළ හැකි සහ ස්ථාවර කුට්ටි වලට බෙදන්න

263            params = buffer.view(-1, sum(self.chunk_size)).split(self.chunk_size, dim=1)

එක්රැස්කිරීමේ මෙහෙයුම සම්පූර්ණ වන තෙක් රැඳී සිටින්න, පසුව අවරෝධක වෙත යොමු කිරීම් ඉවත් කරන්න

265            buffer.record_stream(self.fetch_stream)
266            for b in buffers:
267                b.record_stream(self.fetch_stream)
268            buffer.record_stream(self.fetch_stream)
269            del buffer
270            del buffers

පුහුණුකළ හැකි සහ ස්ථාවර පරාමිතීන් අඛණ්ඩ ආතතීන්ට නැවත සකස් කරන්න

273            params = [p.reshape(-1) for p in params]

තනිපරාමිති ආතතීන් එකතු කරන්න

276            for cont, ps in zip(params, self.param_refs):

පරාමිතීන්නොමැති නම්, මඟ හරින්න

278                if not ps:
279                    continue

අඛණ්ඩආතතියෙන් ඕෆ්සෙට්

282                offset = 0

ආදර්ශපරාමිතීන් හරහා නැවත නැවතත් සහ අඛණ්ඩ tensor සිට අගයන් පැවරීම

284                for p in ps:

මුල්පරාමිති හැඩය

286                    shape = p._orig_shape  # type: ignore[attr-defined]

පරාමිතියේගබඩා ප්රමාණය වෙනස් කරන්න. අපි පරාමිතීන් පිරිසිදු කළ විට මෙය සකස් කරන ලදී.

288                    p.data.storage().resize_(shape.numel())

අඛණ්ඩආතතියෙන් අගයන් පැවරීම

290                    p.data[:] = cont[offset: offset + shape.numel()].reshape(shape)

වෙනත්මෙහෙයුම් සිදු කිරීමට පෙර මෙහෙයුම් සම්පූර්ණ වන තෙක් රැඳී සිටින්න

292                    p.data.record_stream(self.fetch_stream)

ඕෆ්සෙට්යාවත්කාලීන කරන්න

294                    offset += shape.numel()

වෙනත්මෙහෙයුම් සිදු කිරීමට පෙර මෙහෙයුම සම්පූර්ණ වන තෙක් රැඳී සිටින්න

297                cont.record_stream(self.fetch_stream)

300            del params

ඉදිරිසාමාර්ථය

302    def forward(self, *args, **kwargs):

වත්මන්නෝඩයේ සියලු පරාමිතීන් ලබා ගන්න. මෙය පෙර ස්තරය මගින් කැඳවනු ලැබේ, එබැවින් මෙම ඇමතුම පරාමිතීන් ලබා ගත හැකි බවට වග බලා ගැනීම සඳහා පමණි.

309        self.fetch_params()

පරාමිතියසම්පූර්ණ කිරීම සඳහා රැඳී සිටින්න.

312        torch.cuda.current_stream().wait_stream(self.fetch_stream)

ඉදිරියටයන ස්ථරවල පරාමිතීන් ලබා ගැනීම ආරම්භ කරන්න, එවිට වත්මන් ස්තරය එහි ගණනය කිරීම් සිදු කරන ඒවා ලබා ගනු ඇත.

316        for layer in self.next_layer:
317            layer.fetch_params()

ඔටෝග්රාඩ්සක්රීය කර ඇත්නම් වත්මන් ස්ථරයේ පරාමිතීන් සඳහා පසුගාමී කොකු එකතු කරන්න.

320        if torch.is_grad_enabled():
321            self._add_backward_hooks()

වත්මන්ස්ථරයේ ප්රතිදානයන් ගණනය කරන්න

324        res = self.module(*args, **kwargs)

ස්ථරයේපරාමිතීන් පිරිසිදු කරන්න.

ඔටෝග්රාඩ්සක්රීය කර ඇත්නම් පිරිසිදු කිරීම මඟ හරින්න, මෙය ජාලයේ අවසාන ස්තරය වේ, මන්ද පසුගාමී පාස් සඳහා අපට නැවත පරාමිතීන් ලබා ගැනීමට අවශ්ය වනු ඇත.

330        if not torch.is_grad_enabled() or self.next_layer:
331            self._cleanup_params()
332
333        return res

වත්මන්ස්ථරයේ පරාමිතීන් සඳහා පසුගාමී කොකු එකතු කරන්න.

335    def _add_backward_hooks(self):

පසුගාමීකොකු ගණන එකතු කරන ලදි

341        self._backward_hook_handles = 0

වත්මන්ස්ථරයේ පුහුණු කළ හැකි පරාමිතීන් හරහා ලූප්

344        for p in self.param_refs[self.TRAINING_PARAMS_IDX]:

කොක්කක්දැනටමත් එකතු කර නොමැති බවට වග බලා ගන්න

346            assert not hasattr(p, "_hook_handle"), 'Parameter has already been hooked'

අපටබාධා කළ හැකි ස්වයංක්රීය පියවරක් නිර්මාණය expand_as කිරීමට භාවිතා කරන්න

348            p_tmp = p.expand_as(p)

පසුගාමීකොක්ක එක් කිරීමට හසුරුව ලබා ගන්න. මෙම බ්ලොග් අඩවිය ගැන සාකච්ඡා කරයි grad_acc .

351            grad_acc = p_tmp.grad_fn.next_functions[0][0]

පසුගාමීකොක්ක එක් කරන්න

353            handle = grad_acc.register_hook(
354                functools.partial(self._post_backward_hook, p))

හසුරුවගැන සඳහනක් තබා ගන්න

356            p._hook_handle = handle

එකතුකරන ලද කොකු ගණන වැඩි කරන්න

358            self._backward_hook_handles += 1

පසුගාමීසිදුවීමක් හසුරුවන්න

පරාමිතියපසුගාමී කොකු සහ මොඩියුලයේ පසුගාමී කොක්ක මගින් මෙය කැඳවනු ලැබේ.

360    def _backward_event(self):

කොකුකවුන්ටරය අඩු කිරීම

368        self._backward_hook_handles -= 1

සියලුමකොකු (මොඩියුල කොක්ක ඇතුළුව) කැඳවා ඇත්නම්, අපට අනුක්රමික උපස්ථ කර පරාමිතීන් පිරිසිදු කළ හැකිය.

372        if self._backward_hook_handles == -1:
373            self._backup_grads()
374            self._cleanup_params()

පෙරස්ථරයේ පරාමිතීන් ලබා ගැනීම ආරම්භ කරන්න, මන්ද ඔටෝග්රාඩ් ඊළඟට එහි අනුක්රමික ක්රියාවලිය කරනු ඇත.

377        for layer in self.prev_layer:
378            layer.fetch_params()

පරාමිතියපසුගාමී කොක්ක

380    def _post_backward_hook(self, p: nn.Parameter, *args):

පරාමිතියෙන්හසුරුව ඉවත් කරන්න

385        p._hook_handle.remove()  # type: ignore[attr-defined]
386        delattr(p, "_hook_handle")

පසුගාමීසිදුවීමක් හසුරුවන්න

389        self._backward_event()

මොඩියුලයපසුගාමී කොක්ක

391    def _backward_hook(self, *args, **kwargs):

පසුගාමීසිදුවීමක් හසුරුවන්න

396        self._backward_event()

පෙරස්ථරය පරිගණක අනුක්රමික ආරම්භ වනු ඇත. එය පරාම් ලබා ගැනීම අවසන් කර ඇති බවට අප වග බලා ගත යුතුය.

399        torch.cuda.current_stream().wait_stream(self.fetch_stream)

402        return None

වත්මන්ස්ථරයේ අනුක්රමික උපස්ථ කරන්න

404    @torch.no_grad()
405    def _backup_grads(self):

පුහුණුකළ හැකි පරාමිතීන් නොමැති නම් මඟ හරින්න

410        if self.chunk_size[self.TRAINING_PARAMS_IDX] == 0:
411            return

අනුක්රමිකඋපස්ථ කිරීමට උපස්ථ ධාරාව භාවිතා කරන්න

414        with torch.cuda.stream(self.backup_stream):

අනුක්රමිකගබඩා කිරීමට බෆරය

416            buffer = self._empty((self.world_size * self.chunk_size[self.TRAINING_PARAMS_IDX],))

අඛණ්ඩබෆරය නෝඩ් ගණනකට බෙදන්න. මෙම බෙදීම් `බෆර්' පිළිබඳ අදහස් වේ.

418            buffers = list(buffer.split(self.chunk_size[self.TRAINING_PARAMS_IDX]))

අඛණ්ඩබෆරයේ ඕෆ්සෙට්

421            offset = 0

පුහුණුකළ හැකි පරාමිතීන් හරහා නැවත ක්රියාත්මක කරන්න

423            for p in self.param_refs[self.TRAINING_PARAMS_IDX]:

අනුක්රමිකඑකතු

425                shape = p._orig_shape  # type: ignore[attr-defined]
426                buffer[offset: offset + shape.numel()] = p.grad.view(-1)

ඕෆ්සෙට්යාවත්කාලීන කරන්න

428                offset += shape.numel()

අනුක්රමිකපිරිසිදු

430                p.grad = None

වත්මන්ෂාර්ඩ් වල අනුක්රමික සමුච්චය කිරීම සඳහා හිස් ටෙන්සරය

433            grad = self._empty((self.chunk_size[self.TRAINING_PARAMS_IDX],))

එක්එක් ශාකයේ අනුක්රමික සමුච්චය කරන්න. එය නෝඩ් හරහා බෆර විසිරී යන අතර සෑම නෝඩයක්ම එයට ලැබෙන ආතතීන් එකතු වේ (අඩු කරයි).

436            dist.reduce_scatter(grad, buffers)

මෙහෙයුමසම්පූර්ණ වන තෙක් රැඳී සිටින්න, පසුව අවරෝධක වෙත යොමු කිරීම් ඉවත් කරන්න

439            for b in buffers:
440                b.record_stream(self.fetch_stream)
441            buffer.record_stream(self.fetch_stream)
442            del buffer
443            del buffers

කුට්ටිඅනුක්රමික සකසන්න. ප්රශස්තකරණය දකින්නේ මෙයයි.

446            self.chunk[self.TRAINING_PARAMS_IDX].grad = grad
447            del grad

Zero3Layer ස්ථර සඳහා අනුක්රමික මොඩියුලය

450class Zero3Sequential(nn.Module):
  • modules Zero3Layer ස්ථර ලැයිස්තුව
454    def __init__(self, modules: List[Zero3Layer]):
458        super().__init__()

පරාමිතීන්ලබා ගැනීමට CUDA ධාරාව

461        self.fetch_stream = torch.cuda.Stream()

උපස්ථකිරීමට CUDA ධාරාව (සමුච්චය) අනුක්රමික

463        self.backup_stream = torch.cuda.Stream()

එක්එක් Zero3Layer ස්ථරයක් සඳහා ධාරාවන් සහ පෙර සහ ඉදිරියට යන ස්ථර සකසන්න

466        for i in range(len(modules)):

ස්ථරදර්ශකය සකසන්න

468            modules[i].layer_idx = i

ධාරාවන්සකසන්න

470            modules[i].fetch_stream = self.fetch_stream
471            modules[i].backup_stream = self.backup_stream

ඉදිරියටයන ස්ථර සකසන්න

473            if i + 1 < len(modules):
474                modules[i].next_layer.append(modules[i + 1])

පෙරස්ථර සකසන්න

476            if i - 1 >= 0:
477                modules[i].prev_layer.append(modules[i - 1])

මොඩියුලගබඩා ලැයිස්තුව

480        self.module_list = nn.ModuleList(modules)
482    def get_trainable_chunk(self):

එක්එක් ස්ථරයෙන් පුහුණු කළ හැකි කුට්ටි ලැයිස්තුව ආපසු ලබා දෙන්න

484        return sum([m.get_trainable_chunk() for m in self.module_list], [])
486    def forward(self, x: torch.Tensor):

ආපසුදක්වා ඵලය අනුක්රමික සම්පූර්ණ බවට වග බලා ගන්න

488        torch.cuda.current_stream().wait_stream(self.backup_stream)

ඉදිරිසාමාර්ථය

491        for m in self.module_list:
492            x = m(x)

495        return x