Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 90 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export MOJO_RUN_MODE="EAGER"

source code: mojo_opset/backends/ttx/kernels

### UC NPU

UC NPU is a Unified Compiler based backend for Ascend NPU kernels. It is selected with `MOJO_BACKEND="uc"`; the support matrix labels it as `uc_npu`.

### Ixformer

Ixformer is a backend powered by the [ixformer](https://github.com/AIsoftwareFactory/ixformer) library, providing high-performance fused operator implementations for Iluvatar GPUs.
Expand All @@ -49,6 +53,7 @@ You can control the backend you want to use via the `MOJO_BACKEND` environment v

- "ixformer"
- "ttx"
- "uc"
- "torch_npu"
- "torch"

Expand All @@ -58,94 +63,94 @@ When multiple backends are added, Mojo Opset selects the backend implementation

### Core Mojo Operator List

| Op Category | Op Name | torch native | torch_npu | ttx | ixformer |
| :---------- | :------ | :----------- | :-------- | :-- | :------- |
| Activation | `MojoGelu` | ✅ | ✅ | ✅ | TBD |
| Activation | `MojoSilu` | ✅ | ✅ | ✅ | TBD |
| Activation | `MojoSwiGLU` | ✅ | ✅ | ✅ | TBD |
| Activation | `MojoRotateActivation` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPrefillGQA` | ✅ | ✅ | TBD | TBD |
| Attention | `MojoPagedPrefillGQA` | ✅ | ✅ | ✅ | ✅ |
| Attention | `MojoPrefillMLA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPagedPrefillMLA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPrefillNSA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPagedPrefillNSA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoDecodeGQA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPagedDecodeGQA` | ✅ | ✅ | ✅ | ✅ |
| Attention | `MojoDecodeMLA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPagedDecodeMLA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoDecodeNSA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoPagedDecodeNSA` | ✅ | TBD | TBD | TBD |
| Attention | `MojoSdpa` | ✅ | TBD | ✅ | TBD |
| Attention | `MojoPagedPrefillSWA` | ✅ | TBD | ✅ | TBD |
| Attention | `MojoPagedDecodeSWA` | ✅ | TBD | ✅ | TBD |
| Attention | `MojoSWA` | ✅ | TBD | ✅ | TBD |
| KVCache | `MojoStorePagedKVCache` | ✅ | TBD | ✅ | TBD |
| KVCache | `MojoStoreMLAKVCache` | ✅ | TBD | TBD | TBD |
| KVCache | `MojoStorePagedMLAKVCache` | ✅ | TBD | TBD | TBD |
| Gemm | `MojoGemm` | ✅ | TBD | TBD | TBD |
| Gemm | `MojoQuantGemm` | ✅ | ✅ | ✅ | TBD |
| Gemm | `MojoGroupGemm` | ✅ | ✅ | ✅ | TBD |
| ComputeComm | `MojoGemmAll2All` | ✅ | TBD | TBD | TBD |
| ComputeComm | `MojoAllGatherGemm` | ✅ | TBD | TBD | TBD |
| ComputeComm | `MojoGemmAllReduce` | ✅ | TBD | TBD | TBD |
| ComputeComm | `MojoGemmReduceScatter` | ✅ | TBD | TBD | TBD |
| ComputeComm | `MojoQuantGemmAll2All` | ✅ | TBD | TBD | TBD |
| ComputeComm | `MojoAll2AllQuantGemm` | ✅ | TBD | TBD | TBD |
| Embedding | `MojoEmbedding` | ✅ | TBD | TBD | TBD |
| Embedding | `MojoParallelEmbedding` | ✅ | TBD | TBD | TBD |
| OverEncoding | `MojoOverEncoding` | ✅ | TBD | ✅ | TBD |
| OverEncoding | `MojoOverEncodingNGram` | ✅ | TBD | ✅ | TBD |
| Quantize | `MojoStaticQuant` | ✅ | TBD | ✅ | TBD |
| Quantize | `MojoDequant` | ✅ | TBD | TBD | TBD |
| Quantize | `MojoDynamicQuant` | ✅ | ✅ | ✅ | TBD |
| Quantize | `MojoMoEDynamicQuant` | ✅ | ✅ | ✅ | TBD |
| Quantize | `MojoDequantSwiGLUQuant` | ✅ | ✅ | TBD | TBD |
| MoE | `MojoMoE` | ✅ | TBD | TBD | TBD |
| MoE | `MojoMoEGating` | ✅ | TBD | TBD | TBD |
| MoE | `MojoMoEDispatch` | ✅ | TBD | TBD | TBD |
| MoE | `MojoMoEInitRoutingDynamicQuant` | ✅ | TBD | TBD | TBD |
| MoE | `MojoFusedSwiGLUMoEScaleDynamicQuantize` | ✅ | TBD | TBD | TBD |
| MoE | `MojoExperts` | ✅ | TBD | TBD | TBD |
| MoE | `MojoMoECombine` | ✅ | TBD | TBD | TBD |
| MoE | `MojoQuantExperts` | ✅ | TBD | TBD | TBD |
| MoE | `MojoQuantMoE` | ✅ | TBD | TBD | TBD |
| Norm | `MojoLayerNorm` | ✅ | TBD | ✅ | ✅ |
| Norm | `MojoRMSNorm` | ✅ | ✅ | ✅ | ✅ |
| Norm | `MojoGroupLayerNorm` | ✅ | TBD | TBD | TBD |
| Norm | `MojoGroupRMSNorm` | ✅ | TBD | ✅ | TBD |
| Norm | `MojoChannelRMSNorm` | ✅ | TBD | TBD | TBD |
| Norm | `MojoRMSNormQuant` | ✅ | ✅ | TBD | TBD |
| Norm | `MojoLayerNormQuant` | ✅ | ✅ | TBD | TBD |
| Norm | `MojoResidualAddRMSNorm` | ✅ | ✅ | ✅ | ✅ |
| Norm | `MojoResidualAddLayerNorm` | ✅ | TBD | ✅ | ✅ |
| Norm | `MojoResidualAddRMSNormQuant` | ✅ | ✅ | TBD | TBD |
| Norm | `MojoResidualAddLayerNormQuant` | ✅ | ✅ | TBD | TBD |
| Norm | `MojoResidualAddNormCast` | ✅ | TBD | TBD | TBD |
| PositionEmb | `MojoRotaryEmbedding` | ✅ | TBD | ✅ | TBD |
| PositionEmb | `MojoRelativeEmbedding` | ✅ | TBD | ✅ | TBD |
| PositionEmb | `MojoApplyRoPE` | ✅ | ✅ | ✅ | TBD |
| PositionEmb | `MojoRoPEStoreKV` | ✅ | TBD | TBD | TBD |
| PositionEmb | `MojoNormRoPE` | ✅ | TBD | TBD | TBD |
| PositionEmb | `MojoNormRoPEStoreKV` | ✅ | TBD | TBD | TBD |
| PositionEmb | `MojoGridRoPE` | ✅ | TBD | TBD | TBD |
| Sampling | `MojoTopPSampling` | ✅ | TBD | ✅ | TBD |
| Sampling | `MojoTopKSampling` | ✅ | TBD | ✅ | TBD |
| Sampling | `MojoRejectSampling` | ✅ | TBD | ✅ | TBD |
| Sampling | `MojoJoinProbRejectSampling` | ✅ | TBD | ✅ | TBD |
| Sampling | `MojoApplyPenaltiesTempurate` | ✅ | TBD | ✅ | TBD |
| Sampling | `MojoTopPFilter` | ✅ | TBD | ✅ | TBD |
| Convolution | `MojoCausalConv1dUpdateState` | ✅ | TBD | ✅ | TBD |
| MLP | `MojoSwiGLUMLP` | ✅ | TBD | TBD | TBD |
| Indexer | `MojoLightningIndexer` | ✅ | TBD | ✅ | TBD |
| Op Category | Op Name | torch native | torch_npu | ttx | ixformer | uc_npu |
| :---------- | :------ | :----------- | :-------- | :-- | :------- | :----- |
| Activation | `MojoGelu` | ✅ | ✅ | ✅ | TBD | ✅ |
| Activation | `MojoSilu` | ✅ | ✅ | ✅ | TBD | ✅ |
| Activation | `MojoSwiGLU` | ✅ | ✅ | ✅ | TBD | ✅ |
| Activation | `MojoRotateActivation` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPrefillGQA` | ✅ | ✅ | TBD | TBD | TBD |
| Attention | `MojoPagedPrefillGQA` | ✅ | ✅ | ✅ | ✅ | TBD |
| Attention | `MojoPrefillMLA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPagedPrefillMLA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPrefillNSA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPagedPrefillNSA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoDecodeGQA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPagedDecodeGQA` | ✅ | ✅ | ✅ | ✅ | TBD |
| Attention | `MojoDecodeMLA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPagedDecodeMLA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoDecodeNSA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoPagedDecodeNSA` | ✅ | TBD | TBD | TBD | TBD |
| Attention | `MojoSdpa` | ✅ | TBD | ✅ | TBD | TBD |
| Attention | `MojoPagedPrefillSWA` | ✅ | TBD | ✅ | TBD | TBD |
| Attention | `MojoPagedDecodeSWA` | ✅ | TBD | ✅ | TBD | TBD |
| Attention | `MojoSWA` | ✅ | TBD | ✅ | TBD | TBD |
| KVCache | `MojoStorePagedKVCache` | ✅ | TBD | ✅ | TBD | TBD |
| KVCache | `MojoStoreMLAKVCache` | ✅ | TBD | TBD | TBD | TBD |
| KVCache | `MojoStorePagedMLAKVCache` | ✅ | TBD | TBD | TBD | TBD |
| Gemm | `MojoGemm` | ✅ | TBD | TBD | TBD | TBD |
| Gemm | `MojoQuantGemm` | ✅ | ✅ | ✅ | TBD | ✅ |
| Gemm | `MojoGroupGemm` | ✅ | ✅ | ✅ | TBD | TBD |
| ComputeComm | `MojoGemmAll2All` | ✅ | TBD | TBD | TBD | TBD |
| ComputeComm | `MojoAllGatherGemm` | ✅ | TBD | TBD | TBD | TBD |
| ComputeComm | `MojoGemmAllReduce` | ✅ | TBD | TBD | TBD | TBD |
| ComputeComm | `MojoGemmReduceScatter` | ✅ | TBD | TBD | TBD | TBD |
| ComputeComm | `MojoQuantGemmAll2All` | ✅ | TBD | TBD | TBD | TBD |
| ComputeComm | `MojoAll2AllQuantGemm` | ✅ | TBD | TBD | TBD | TBD |
| Embedding | `MojoEmbedding` | ✅ | TBD | TBD | TBD | TBD |
| Embedding | `MojoParallelEmbedding` | ✅ | TBD | TBD | TBD | TBD |
| OverEncoding | `MojoOverEncoding` | ✅ | TBD | ✅ | TBD | TBD |
| OverEncoding | `MojoOverEncodingNGram` | ✅ | TBD | ✅ | TBD | TBD |
| Quantize | `MojoStaticQuant` | ✅ | TBD | ✅ | TBD | TBD |
| Quantize | `MojoDequant` | ✅ | TBD | TBD | TBD | TBD |
| Quantize | `MojoDynamicQuant` | ✅ | ✅ | ✅ | TBD | ✅ |
| Quantize | `MojoMoEDynamicQuant` | ✅ | ✅ | ✅ | TBD | ✅ |
| Quantize | `MojoDequantSwiGLUQuant` | ✅ | ✅ | TBD | TBD | TBD |
| MoE | `MojoMoE` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoMoEGating` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoMoEDispatch` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoMoEInitRoutingDynamicQuant` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoFusedSwiGLUMoEScaleDynamicQuantize` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoExperts` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoMoECombine` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoQuantExperts` | ✅ | TBD | TBD | TBD | TBD |
| MoE | `MojoQuantMoE` | ✅ | TBD | TBD | TBD | TBD |
| Norm | `MojoLayerNorm` | ✅ | TBD | ✅ | ✅ | ✅ |
| Norm | `MojoRMSNorm` | ✅ | ✅ | ✅ | ✅ | ✅ |
| Norm | `MojoGroupLayerNorm` | ✅ | TBD | TBD | TBD | TBD |
| Norm | `MojoGroupRMSNorm` | ✅ | TBD | ✅ | TBD | TBD |
| Norm | `MojoChannelRMSNorm` | ✅ | TBD | TBD | TBD | TBD |
| Norm | `MojoRMSNormQuant` | ✅ | ✅ | TBD | TBD | TBD |
| Norm | `MojoLayerNormQuant` | ✅ | ✅ | TBD | TBD | TBD |
| Norm | `MojoResidualAddRMSNorm` | ✅ | ✅ | ✅ | ✅ | ✅ |
| Norm | `MojoResidualAddLayerNorm` | ✅ | TBD | ✅ | ✅ | ✅ |
| Norm | `MojoResidualAddRMSNormQuant` | ✅ | ✅ | TBD | TBD | TBD |
| Norm | `MojoResidualAddLayerNormQuant` | ✅ | ✅ | TBD | TBD | TBD |
| Norm | `MojoResidualAddNormCast` | ✅ | TBD | TBD | TBD | TBD |
| PositionEmb | `MojoRotaryEmbedding` | ✅ | TBD | ✅ | TBD | ✅ |
| PositionEmb | `MojoRelativeEmbedding` | ✅ | TBD | ✅ | TBD | TBD |
| PositionEmb | `MojoApplyRoPE` | ✅ | ✅ | ✅ | TBD | ✅ |
| PositionEmb | `MojoRoPEStoreKV` | ✅ | TBD | TBD | TBD | TBD |
| PositionEmb | `MojoNormRoPE` | ✅ | TBD | TBD | TBD | TBD |
| PositionEmb | `MojoNormRoPEStoreKV` | ✅ | TBD | TBD | TBD | TBD |
| PositionEmb | `MojoGridRoPE` | ✅ | TBD | TBD | TBD | TBD |
| Sampling | `MojoTopPSampling` | ✅ | TBD | ✅ | TBD | TBD |
| Sampling | `MojoTopKSampling` | ✅ | TBD | ✅ | TBD | TBD |
| Sampling | `MojoRejectSampling` | ✅ | TBD | ✅ | TBD | TBD |
| Sampling | `MojoJoinProbRejectSampling` | ✅ | TBD | ✅ | TBD | TBD |
| Sampling | `MojoApplyPenaltiesTempurate` | ✅ | TBD | ✅ | TBD | TBD |
| Sampling | `MojoTopPFilter` | ✅ | TBD | ✅ | TBD | TBD |
| Convolution | `MojoCausalConv1dUpdateState` | ✅ | TBD | ✅ | TBD | TBD |
| MLP | `MojoSwiGLUMLP` | ✅ | TBD | TBD | TBD | TBD |
| Indexer | `MojoLightningIndexer` | ✅ | TBD | ✅ | TBD | TBD |

### Experimental Mojo Operator List

| Op Category | Op Name | torch native | torch_npu | ttx | ixformer |
| :---------- | :------ | :----------- | :-------- | :-- | :------- |
| Experimental | `MojoQuantBatchGemmReduceSum` | ✅ | ✅ | ✅ | TBD |
| Experimental | `MojoIndexer` | ✅ | TBD | ✅ | TBD |
| Experimental | `MojoStoreLowrank` | ✅ | TBD | ✅ | TBD |
| Op Category | Op Name | torch native | torch_npu | ttx | ixformer | uc_npu |
| :---------- | :------ | :----------- | :-------- | :-- | :------- | :----- |
| Experimental | `MojoQuantBatchGemmReduceSum` | ✅ | ✅ | ✅ | TBD | TBD |
| Experimental | `MojoIndexer` | ✅ | TBD | ✅ | TBD | TBD |
| Experimental | `MojoStoreLowrank` | ✅ | TBD | ✅ | TBD | TBD |

### Core Mojo Function List

Expand Down
17 changes: 16 additions & 1 deletion mojo_opset/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,22 @@
logger.warning("Skipping ixformer backend (import failed): %s", e)

if platform in _SUPPORT_TTX_PLATFROM:
from .ttx import *
try:
from .ttx import *
except Exception as e:
logger.warning("Skipping ttx backend (import failed): %s", e)

if platform in _SUPPORT_TORCH_NPU_PLATFROM:
from .torch_npu import *

if platform in _SUPPORT_TORCH_NPU_PLATFROM:
try:
from .uc import *
except ImportError as e:
logger.warning("Skipping uc backend (import failed): %s", e)

if platform == "npu" and get_bool_env("MOJO_DETERMINISTIC", default=False):
import os

# special setting for npu deterministic matmul
os.environ["CLOSE_MATMUL_K_SHIFT"] = "1"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block of code is completely redundant. Setting CLOSE_MATMUL_K_SHIFT when MOJO_DETERMINISTIC is enabled is already handled at lines 11-17. Removing this redundant block keeps the code clean and maintainable.

5 changes: 5 additions & 0 deletions mojo_opset/backends/uc/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from mojo_opset.utils.platform import get_impl_by_platform

_op_map = get_impl_by_platform()
globals().update(_op_map)
__all__ = list(_op_map.keys())
Comment on lines +1 to +5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The uc backend will be imported and registered even if uc_kernel is not installed, because uc_kernel is only imported lazily at runtime. If the uc backend is selected or fell back to, it will crash at runtime with an ImportError. Checking for uc_kernel availability at import time allows the backend to be gracefully skipped and logged as a warning.

Suggested change
from mojo_opset.utils.platform import get_impl_by_platform
_op_map = get_impl_by_platform()
globals().update(_op_map)
__all__ = list(_op_map.keys())
import importlib.util
if importlib.util.find_spec("uc_kernel") is None:
raise ImportError("uc_kernel is not installed, which is required by the uc backend.")
from mojo_opset.utils.platform import get_impl_by_platform
_op_map = get_impl_by_platform()
globals().update(_op_map)
__all__ = list(_op_map.keys())

1 change: 1 addition & 0 deletions mojo_opset/backends/uc/operators/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

70 changes: 70 additions & 0 deletions mojo_opset/backends/uc/operators/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from functools import lru_cache

import torch


_DTYPE_API_SUFFIX = {
torch.float16: "fp16",
torch.bfloat16: "bf16",
torch.float32: "fp32",
}


@lru_cache(maxsize=1)
def _uc_kernels():
import uc_kernel

return uc_kernel.load()


def _matrix_shape(tensor: torch.Tensor) -> tuple[int, int]:
if tensor.dim() == 0:
return 1, 1
if tensor.dim() == 1:
return 1, tensor.numel()
return tensor.numel() // tensor.shape[-1], tensor.shape[-1]


def _typed_api(api: str, dtype: torch.dtype) -> str:
suffix = _DTYPE_API_SUFFIX.get(dtype)
if suffix is None:
raise NotImplementedError(f"UC backend {api} does not support dtype {dtype}.")

kernels = _uc_kernels()
typed_api = f"{api}_{suffix}"
if typed_api in kernels.keys():
return typed_api
if dtype == torch.float16 and api in kernels.keys():
return api

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In Python, checking membership directly in a dictionary (e.g., key in dict) is more idiomatic and significantly faster than calling .keys() (e.g., key in dict.keys()), which creates an unnecessary view object.

Suggested change
if typed_api in kernels.keys():
return typed_api
if dtype == torch.float16 and api in kernels.keys():
return api
if typed_api in kernels:
return typed_api
if dtype == torch.float16 and api in kernels:
return api

raise NotImplementedError(f"UC backend {api} does not provide a {suffix} kernel artifact.")


def run_unary_kernel(api: str, x: torch.Tensor) -> torch.Tensor:
if x.numel() == 0:
return torch.empty_like(x)

kernel_input = x.contiguous()
kernel_output = torch.empty_like(kernel_input)
rows, cols = _matrix_shape(kernel_input)
_uc_kernels()[_typed_api(api, kernel_input.dtype)](kernel_input, kernel_output, rows, cols)
return kernel_output.reshape(x.shape)


def run_binary_kernel(api: str, lhs: torch.Tensor, rhs: torch.Tensor) -> torch.Tensor:
if lhs.shape != rhs.shape:
raise ValueError(f"UC backend {api} expects matching input shapes, got {lhs.shape} and {rhs.shape}.")
if lhs.dtype != rhs.dtype:
raise ValueError(f"UC backend {api} expects matching input dtypes, got {lhs.dtype} and {rhs.dtype}.")
if lhs.numel() == 0:
return torch.empty_like(lhs)

kernel_lhs = lhs.contiguous()
kernel_rhs = rhs.contiguous()
kernel_output = torch.empty_like(kernel_lhs)
rows, cols = _matrix_shape(kernel_lhs)
_uc_kernels()[_typed_api(api, kernel_lhs.dtype)](kernel_lhs, kernel_rhs, kernel_output, rows, cols)
return kernel_output.reshape(lhs.shape)


def run_kernel(api: str, dtype: torch.dtype, *args) -> None:
_uc_kernels()[_typed_api(api, dtype)](*args)
31 changes: 31 additions & 0 deletions mojo_opset/backends/uc/operators/activation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import torch

from mojo_opset.core import MojoGelu
from mojo_opset.core import MojoSilu
from mojo_opset.core import MojoSwiGLU

from ._utils import run_binary_kernel
from ._utils import run_unary_kernel


class UCGelu(MojoGelu):
supported_platforms_list = ["npu"]

def forward(self, x: torch.Tensor) -> torch.Tensor:
return run_unary_kernel("mojo_gelu", x)


class UCSilu(MojoSilu):
supported_platforms_list = ["npu"]

def forward(self, x: torch.Tensor) -> torch.Tensor:
return run_unary_kernel("mojo_silu", x)


class UCSwiGLU(MojoSwiGLU):
supported_platforms_list = ["npu"]

def forward(self, gate_out: torch.Tensor, up_out: torch.Tensor) -> torch.Tensor:
if self.swiglu_limit > 0:
return super().forward(gate_out, up_out)
return run_binary_kernel("mojo_swiglu", gate_out, up_out)
Loading
Loading