-
Notifications
You must be signed in to change notification settings - Fork 642
feat: NPU (Ascend 910B3) support for RFdiffusion inference #459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -233,7 +233,7 @@ def reset_parameter(self): | |
| nn.init.zeros_(self.embed_e1.bias) | ||
| nn.init.zeros_(self.embed_e2.bias) | ||
|
|
||
| @torch.cuda.amp.autocast(enabled=False) | ||
| @torch.amp.autocast(device_type="npu", enabled=False) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This hardcodes device_type="npu", so on CUDA systems this decorator no longer disables autocast, meaning torch.cuda.amp.autocast(enabled=False)'s effect is lost. Should be conditional on the active device. |
||
| def forward(self, msa, pair, R_in, T_in, xyz, state, idx, motif_mask, cyclic_reses=None, top_k=64, eps=1e-5): | ||
| B, N, L = msa.shape[:3] | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import torch | ||
|
|
||
| try: | ||
| import torch_npu | ||
| torch.npu.config.allow_internal_format = False | ||
|
|
||
| # Patch torch.cdist for NPU (NPU does not support cdist natively) | ||
| _orig_cdist = torch.cdist | ||
| def _npu_cdist(x1, x2, p=2.0, compute_mode='use_mm_for_euclid_dist_if_necessary', **kwargs): | ||
| if x1.device.type == 'npu' or (x2 is not None and hasattr(x2, 'device') and x2.device.type == 'npu'): | ||
| if x1.dim() == 2: | ||
| x1 = x1.unsqueeze(0) | ||
| x2 = x2.unsqueeze(0) | ||
| squeeze = True | ||
| else: | ||
| squeeze = False | ||
| x1_sq = (x1 * x1).sum(dim=-1, keepdim=True) | ||
| x2_sq = (x2 * x2).sum(dim=-1, keepdim=True) | ||
| cross = torch.bmm(x1, x2.transpose(-1, -2)) | ||
| dist_sq = x1_sq + x2_sq.transpose(-1, -2) - 2 * cross | ||
| dist_sq = dist_sq.clamp(min=0) | ||
| result = torch.sqrt(dist_sq + 1e-12) | ||
| if squeeze: | ||
| result = result.squeeze(0) | ||
| return result | ||
| return _orig_cdist(x1, x2, p=p, compute_mode=compute_mode, **kwargs) | ||
| torch.cdist = _npu_cdist | ||
| except ImportError: | ||
| pass |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,8 +48,8 @@ def initialize(self, conf: DictConfig) -> None: | |
|
|
||
| """ | ||
| self._log = logging.getLogger(__name__) | ||
| if torch.cuda.is_available(): | ||
| self.device = torch.device("cuda") | ||
| if torch.npu.is_available(): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please back in the check for |
||
| self.device = torch.device("npu") | ||
| else: | ||
| self.device = torch.device("cpu") | ||
| needs_model_reload = ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,8 @@ | |
| import re | ||
| import os, time, pickle | ||
| import torch | ||
| import torch_npu | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Many users of RFD only have access to GPU/CPU resources. Adding this import statement not in a try/except will make it impossible to run on GPU systems. I suggest wrapping it like you do in |
||
| torch.npu.config.allow_internal_format = False | ||
| from omegaconf import OmegaConf | ||
| import hydra | ||
| import logging | ||
|
|
@@ -41,13 +43,16 @@ def main(conf: HydraConfig) -> None: | |
| if conf.inference.deterministic: | ||
| make_deterministic() | ||
|
|
||
| # Check for available GPU and print result of check | ||
| if torch.cuda.is_available(): | ||
| # Check for available NPU/GPU and print result of check | ||
| if torch.npu.is_available(): | ||
| device_name = torch.npu.get_device_name(torch.npu.current_device()) | ||
| log.info(f"Found NPU with device_name {device_name}. Will run RFdiffusion on {device_name}") | ||
| elif torch.cuda.is_available(): | ||
| device_name = torch.cuda.get_device_name(torch.cuda.current_device()) | ||
| log.info(f"Found GPU with device_name {device_name}. Will run RFdiffusion on {device_name}") | ||
| else: | ||
| log.info("////////////////////////////////////////////////") | ||
| log.info("///// NO GPU DETECTED! Falling back to CPU /////") | ||
| log.info("///// NO GPU/NPU DETECTED! Falling back to CPU /////") | ||
| log.info("////////////////////////////////////////////////") | ||
|
|
||
| # Initialize sampler and target/contig. | ||
|
|
@@ -148,9 +153,11 @@ def main(conf: HydraConfig) -> None: | |
| trb = dict( | ||
| config=OmegaConf.to_container(sampler._conf, resolve=True), | ||
| plddt=plddt_stack.cpu().numpy(), | ||
| device=torch.cuda.get_device_name(torch.cuda.current_device()) | ||
| if torch.cuda.is_available() | ||
| else "CPU", | ||
| device=torch.npu.get_device_name(torch.npu.current_device()) | ||
| if torch.npu.is_available() | ||
| else (torch.cuda.get_device_name(torch.cuda.current_device()) | ||
| if torch.cuda.is_available() | ||
| else "CPU"), | ||
| time=time.time() - start_time, | ||
| ) | ||
| if hasattr(sampler, "contig_map"): | ||
|
|
@@ -188,8 +195,11 @@ def main(conf: HydraConfig) -> None: | |
| chain_ids=sampler.chain_idx, | ||
| ) | ||
|
|
||
| if conf.inference.empty_cache_per_design and torch.cuda.is_available(): | ||
| torch.cuda.empty_cache() | ||
| if conf.inference.empty_cache_per_design: | ||
| if torch.npu.is_available(): | ||
| torch.npu.empty_cache() | ||
| elif torch.cuda.is_available(): | ||
| torch.cuda.empty_cache() | ||
|
|
||
| log.info(f"Finished design in {(time.time()-start_time)/60:.2f} minutes") | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of this for a manual implementation should be conditioned on the device type, similar to how the nvtx changes are.