|
10 | 10 |
|
11 | 11 | __all__ = [ |
12 | 12 | "generic_gemm_fl", |
| 13 | + "te_general_grouped_gemm_fl", |
13 | 14 | ] |
14 | 15 |
|
15 | 16 | _DTYPE_TO_TORCH = { |
@@ -115,3 +116,107 @@ def generic_gemm_fl( |
115 | 116 | return D, bias_grad, gelu_input, extra_output_ret |
116 | 117 | else: |
117 | 118 | return out1, bias_grad, gelu_input, extra_output_ret |
| 119 | + |
| 120 | + |
| 121 | +# This function can represent both forward and backward computations. |
| 122 | +# When grad is False (forward computation), the 'bias' is bias; |
| 123 | +# When grad is True (backward computation/gradient calculation), the 'bias' is grad_bias; |
| 124 | +def te_general_grouped_gemm_fl( |
| 125 | + B: List[torch.Tensor], |
| 126 | + transb: bool, |
| 127 | + A: List[torch.Tensor], |
| 128 | + transa: bool, |
| 129 | + D: Optional[List[torch.Tensor]], |
| 130 | + D_type: Any, |
| 131 | + m_splits: List[int], |
| 132 | + bias: List[torch.Tensor], # bias or grad_bias |
| 133 | + bias_type: Any, |
| 134 | + single_output: bool, |
| 135 | + pre_gelu_out: List[torch.Tensor], |
| 136 | + grad: bool, |
| 137 | + workspace: List[torch.Tensor], |
| 138 | + workspaceSize: int, |
| 139 | + accumulate: bool, |
| 140 | + use_split_accumulator: bool, |
| 141 | + math_sm_count: int, |
| 142 | +) -> Optional[List[torch.Tensor]]: |
| 143 | + if single_output and D is None: |
| 144 | + raise ValueError("not implemented, D should be allocated for single output case.") |
| 145 | + |
| 146 | + num_gemms = len(A) |
| 147 | + if D is None: |
| 148 | + D = [] |
| 149 | + for i in range(num_gemms): |
| 150 | + m = A[i].shape[1] if transa else A[i].shape[0] |
| 151 | + n = B[i].shape[0] if transb else B[i].shape[1] |
| 152 | + D.append(torch.empty((m, n), dtype=D[i].dtype, device=A[0].device)) |
| 153 | + |
| 154 | + temp_D = [] |
| 155 | + for i in range(num_gemms): |
| 156 | + # Handle the special case of zero-element inputs |
| 157 | + if A[i].numel() == 0 or B[i].numel() == 0: |
| 158 | + if not single_output: |
| 159 | + if D[i].numel() != 0 and not accumulate: |
| 160 | + flag_gems.copy_(D[i], flag_gems.zeros(D[i].shape)) |
| 161 | + else: |
| 162 | + out = flag_gems.zeros((A[i].shape[0], B[i].shape[1])) |
| 163 | + if grad and len(bias) > i and bias[i] is not None and bias[i].numel() != 0: |
| 164 | + flag_gems.copy_(bias[i], flag_gems.zeros(bias[i].shape)) |
| 165 | + if ( |
| 166 | + len(pre_gelu_out) > i |
| 167 | + and pre_gelu_out[i] is not None |
| 168 | + and pre_gelu_out[i].numel() != 0 |
| 169 | + ): |
| 170 | + flag_gems.copy_(pre_gelu_out[i], flag_gems.zeros(pre_gelu_out[i].shape)) |
| 171 | + continue |
| 172 | + |
| 173 | + a = A[i].t() if transa else A[i] |
| 174 | + b = B[i].t() if transb else B[i] |
| 175 | + # Determine presence of epilogue tensors |
| 176 | + has_bias = len(bias) > i and bias[i] is not None and bias[i].numel() > 0 |
| 177 | + has_pre_gelu = ( |
| 178 | + len(pre_gelu_out) > i and pre_gelu_out[i] is not None and pre_gelu_out[i].numel() > 0 |
| 179 | + ) |
| 180 | + |
| 181 | + # Forward Pass calculation |
| 182 | + if not grad: |
| 183 | + if has_bias: |
| 184 | + # Fused matrix multiplication and bias addition |
| 185 | + out = flag_gems.addmm(bias[i], a, b) |
| 186 | + else: |
| 187 | + out = flag_gems.mm(a, b) |
| 188 | + |
| 189 | + # Apply GELU epilogue if pre_gelu_out is provided |
| 190 | + if has_pre_gelu: |
| 191 | + flag_gems.copy_(pre_gelu_out[i], out) |
| 192 | + out = flag_gems.gelu(out) |
| 193 | + else: |
| 194 | + out = flag_gems.mm(a, b) |
| 195 | + |
| 196 | + # Apply dGELU epilogue if requested |
| 197 | + if has_pre_gelu: |
| 198 | + out = flag_gems.gelu_backward(out, pre_gelu_out[i]) |
| 199 | + |
| 200 | + # Compute bias gradients if requested |
| 201 | + if has_bias: |
| 202 | + bias_grad = flag_gems.sum_dim(out, dim=[0]) |
| 203 | + if accumulate: |
| 204 | + flag_gems.add_(bias[i], bias_grad) |
| 205 | + else: |
| 206 | + flag_gems.copy_(bias[i], bias_grad) |
| 207 | + |
| 208 | + if not single_output: |
| 209 | + # Store output |
| 210 | + if accumulate: |
| 211 | + flag_gems.add_(D[i], out.to(D[i].dtype)) |
| 212 | + else: |
| 213 | + flag_gems.copy_(D[i], out.to(D[i].dtype)) |
| 214 | + else: |
| 215 | + temp_D.append(out.to(D[0].dtype)) |
| 216 | + |
| 217 | + if single_output: |
| 218 | + if temp_D: |
| 219 | + temp = flag_gems.cat(temp_D, dim=0) |
| 220 | + flag_gems.copy_(D[0], temp) |
| 221 | + |
| 222 | + return bias |
0 commit comments