| 214 | self.attention_op: Optional[Any] = None |
| 215 | |
| 216 | def forward(self, x, context=None, mask=None): |
| 217 | q = self.to_q(x) |
| 218 | context = default(context, x) |
| 219 | k = self.to_k(context) |
| 220 | v = self.to_v(context) |
| 221 | |
| 222 | b, _, _ = q.shape |
| 223 | q, k, v = map( |
| 224 | lambda t: t.unsqueeze(3) |
| 225 | .reshape(b, t.shape[1], self.heads, self.dim_head) |
| 226 | .permute(0, 2, 1, 3) |
| 227 | .reshape(b * self.heads, t.shape[1], self.dim_head) |
| 228 | .contiguous(), |
| 229 | (q, k, v), |
| 230 | ) |
| 231 | |
| 232 | # actually compute the attention, what we cannot get enough of |
| 233 | out = xformers.ops.memory_efficient_attention(q, k, v, attn_bias=None, op=self.attention_op) |
| 234 | |
| 235 | if exists(mask): |
| 236 | raise NotImplementedError |
| 237 | out = ( |
| 238 | out.unsqueeze(0) |
| 239 | .reshape(b, self.heads, out.shape[1], self.dim_head) |
| 240 | .permute(0, 2, 1, 3) |
| 241 | .reshape(b, out.shape[1], self.heads * self.dim_head) |
| 242 | ) |
| 243 | return self.to_out(out) |
| 244 | |
| 245 | |
| 246 | class BasicTransformerBlock(nn.Module): |