compile_fail
10_GFVLA_FusedPairwiseNodeAggregate.py
started
2026-05-05T00:54:13Z
compile error: Error building extension 'gf_vla_fused_pairwise_node_ext': [1/3] /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=gf_vla_fused_pairwise_node_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/include/python3.10 -fPIC -std=c++17 -O3 -c /scratch/abaner/KernelBench/runs/l123_single_gpt/popcorn/gpt-5.5-priority/level_2_problem_10_cache
timingkernelbench.timing
kernel mean / median / std
—
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
import torch.nn.functional as F
# Default ModelNew is PyTorch-only. run_and_check: use check_kernel=False with backend=cuda
# until the candidate file contains a real CUDA kernel (see kernel_static_checker).
class Model(nn.Module):
"""
GF-VLA style **fused pairwise → node** scene-graph readout.
For every ordered pair (i, j), fuse ``[node_i || node_j || pair_feat_ij]`` with
an MLP, mask invalid graph edges, then **max-pool over outgoing neighbors j**
to produce an updated per-object signal (object-centric scene graph refresh).
Complements ``7_GFVLA_FusedSceneGraphUpdate`` (attention) with an MLP + reduce
fusion pattern common for relation classifiers and affordance heads.
"""
def __init__(self, dim: int, pair_dim: int, hidden: int):
super().__init__()
self.dim = dim
self.pair_dim = pair_dim
self.fuse = nn.Sequential(
nn.Linear(2 * dim + pair_dim, hidden),
nn.SiLU(),
nn.Linear(hidden, dim),
)
self.out_norm = nn.LayerNorm(dim)
def forward(
self,
nodes: torch.Tensor,
pair_feats: torch.Tensor,
edge_mask: torch.Tensor,
) -> torch.Tensor:
"""
Args:
nodes: (B, N, D)
pair_feats: (B, N, N, P)
edge_mask: (B, N, N) float {0,1}
Returns:
(B, N, D) residual ``nodes + LN( max_j fuse(...) )``
"""
B, N, D = nodes.shape
assert pair_feats.shape == (B, N, N, self.pair_dim)
hi = nodes.unsqueeze(2).expand(-1, -1, N, -1)
hj = nodes.unsqueeze(1).expand(-1, N, -1, -1)
fused = self.fuse(torch.cat([hi, hj, pair_feats], dim=-1))
neg = torch.finfo(fused.dtype).min
fused = fused.masked_fill(edge_mask.unsqueeze(-1) < 0.5, neg)
pooled, _ = fused.max(dim=2)
return nodes + self.out_norm(pooled)
class ModelNew(nn.Module):
"""KernelBench candidate entry point; default delegates to ``Model``."""
def __init__(self, dim: int, pair_dim: int, hidden: int):
super().__init__()
self._impl = Model(dim, pair_dim, hidden)
def forward(
self,
nodes: torch.Tensor,
pair_feats: torch.Tensor,
edge_mask: torch.Tensor,
) -> torch.Tensor:
return self._impl(nodes, pair_feats, edge_mask)
batch_size = 4
num_objects = 24
dim = 96
pair_dim = 16
hidden = 192
def get_inputs():
p = popcorn_pri
nodes = torch.randn(p.jitter_int(batch_size), p.jitter_int(num_objects), dim)
pair_feats = torch.randn(p.jitter_int(batch_size), p.jitter_int(num_objects), p.jitter_int(num_objects), pair_dim)
edge_mask = torch.ones(p.jitter_int(batch_size), p.jitter_int(num_objects), p.jitter_int(num_objects))
return [nodes, pair_feats, edge_mask]
def get_init_inputs():
return [dim, pair_dim, hidden]
turn 0 · FINAL · 1 tool call(s) · 51.5s turn · 51.5s LLM · 13,859 chars (click to expand)
turn 051.5s turn · 51.5s LLM · 0.0s tools · FINAL
reasoning
**Evaluating operations and performance**
This is a big deal: I’m looking at a system with a lot of components, calculating B*N*D = 9216 elements multiplied by N = 24 and H = 192, which leads to around 8.8 billion operations. I realize that using PyTorch’s matmul is fast but cumbersome. I wonder if I could create a custom kernel to make it even quicker, especially for smaller sizes. Should I stick with PyTorch for the MLP and then replace the forward with a custom CUDA kernel? There's a lot to think about, but efficiency is critical!
**Evaluating matrix multiplication in PyTorch**
I'm analyzing how matmul order differs between frameworks, with possible output value errors exceeding 1e-4. I suspect that PyTorch's linear operations might be more deterministic, especially if TF32 is enabled. If default settings apply, it seems these might operate on TF32 unless specified otherwise. Errors around 1e-5 during sequential operations also concern me, and I’m debating whether to use fast_math for performance at the cost of potential numerical issues. I need to balance speed with accuracy.
**Planning tool call structure**
I’m aware that I only have one tool call to make, so I need to be efficient with my final output. It should be structured as JSON, ensuring all necessary elements are included. I have to think through exactly what I need to include in that output and how to arrange it properly. It's essential to get this right since there's no room for mistakes here. I want to make sure everything is clean and well-organized!
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor fused_forward(torch::Tensor nodes,\n torch::Tensor pair_feats,\n torch::Tensor edge_mask,\n torch::Tensor w1,\n torch::Tensor b1,\n torch::Tensor w2,\n torch::Tensor b2,\n torch::Tensor ln_w,\n torch::Tensor ln_b,\n int64_t dim,\n int64_t pair_dim,\n int64_t hidden);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cfloat>\n\n__global__ void fc1_silu_kernel(const float* __restrict__ nodes,\n const float* __restrict__ pair_feats,\n const float* __restrict__ w1,\n const float* __restrict__ b1,\n float* __restrict__ hidden_out,\n int B, int N, int D, int P, int H) {\n int pair_idx = blockIdx.x;\n int j = pair_idx % N;\n int t = pair_idx / N;\n int i = t % N;\n int b = t / N;\n int IN = 2 * D + P;\n\n const float* ni = nodes + (b * N + i) * D;\n const float* nj = nodes + (b * N + j) * D;\n const float* pf = pair_feats + ((b * N + i) * N + j) * P;\n float* hout = hidden_out + ((b * N + i) * N + j) * H;\n\n for (int k = threadIdx.x; k < H; k += blockDim.x) {\n const float* wk = w1 + k * IN;\n float acc = b1[k];\n #pragma unroll 4\n for (int d = 0; d < D; ++d) acc = fmaf(ni[d], wk[d], acc);\n #pragma unroll 4\n for (int d = 0; d < D; ++d) acc = fmaf(nj[d], wk[D + d], acc);\n #pragma unroll 4\n for (int p = 0; p < P; ++p) acc = fmaf(pf[p], wk[2 * D + p], acc);\n float sig = 1.0f / (1.0f + expf(-acc));\n hout[k] = acc * sig;\n }\n}\n\n__global__ void fc2_max_kernel(const float* __restrict__ hidden,\n const float* __restrict__ edge_mask,\n const float* __restrict__ w2,\n const float* __restrict__ b2,\n float* __restrict__ pooled,\n int B, int N, int D, int H) {\n extern __shared__ float sh[];\n int idx = blockIdx.x;\n int d = idx % D;\n int row = idx / D; // b*N+i\n int tid = threadIdx.x;\n int b = row / N;\n int i = row - b * N;\n\n float maxv = -FLT_MAX;\n const float* wd = w2 + d * H;\n for (int j = 0; j < N; ++j) {\n float m = edge_mask[(row * N) + j];\n float part = 0.0f;\n if (m >= 0.5f) {\n const float* hptr = hidden + (row * N + j) * H;\n for (int k = tid; k < H; k += blockDim.x) {\n part = fmaf(hptr[k], wd[k], part);\n }\n }\n sh[tid] = part;\n __syncthreads();\n for (int s = blockDim.x >> 1; s > 0; s >>= 1) {\n if (tid < s) sh[tid] += sh[tid + s];\n __syncthreads();\n }\n if (tid == 0 && m >= 0.5f) {\n float val = sh[0] + b2[d];\n maxv = fmaxf(maxv, val);\n }\n __syncthreads();\n }\n if (tid == 0) pooled[row * D + d] = maxv;\n}\n\n__global__ void layernorm_residual_kernel(const float* __restrict__ nodes,\n const float* __restrict__ pooled,\n const float* __restrict__ ln_w,\n const float* __restrict__ ln_b,\n float* __restrict__ out,\n int rows, int D) {\n extern __shared__ float sh[];\n int row = blockIdx.x;\n int tid = threadIdx.x;\n\n float sum = 0.0f;\n for (int d = tid; d < D; d += blockDim.x) sum += pooled[row * D + d];\n sh[tid] = sum;\n __syncthreads();\n for (int s = blockDim.x >> 1; s > 0; s >>= 1) {\n if (tid < s) sh[tid] += sh[tid + s];\n __syncthreads();\n }\n float mean = sh[0] / (float)D;\n\n float vsum = 0.0f;\n for (int d = tid; d < D; d += blockDim.x) {\n float x = pooled[row * D + d] - mean;\n vsum = fmaf(x, x, vsum);\n }\n sh[tid] = vsum;\n __syncthreads();\n for (int s = blockDim.x >> 1; s > 0; s >>= 1) {\n if (tid < s) sh[tid] += sh[tid + s];\n __syncthreads();\n }\n float invstd = rsqrtf(sh[0] / (float)D + 1.0e-5f);\n\n for (int d = tid; d < D; d += blockDim.x) {\n int off = row * D + d;\n float y = (pooled[off] - mean) * invstd;\n out[off] = nodes[off] + y * ln_w[d] + ln_b[d];\n }\n}\n\ntorch::Tensor fused_forward(torch::Tensor nodes,\n torch::Tensor pair_feats,\n torch::Tensor edge_mask,\n torch::Tensor w1,\n torch::Tensor b1,\n torch::Tensor w2,\n torch::Tensor b2,\n torch::Tensor ln_w,\n torch::Tensor ln_b,\n int64_t dim,\n int64_t pair_dim,\n int64_t hidden_size) {\n int B = (int)nodes.size(0);\n int N = (int)nodes.size(1);\n int D = (int)dim;\n int P = (int)pair_dim;\n int H = (int)hidden_size;\n\n auto opts = nodes.options();\n torch::Tensor hidden = torch::empty({B, N, N, H}, opts);\n torch::Tensor pooled = torch::empty({B, N, D}, opts);\n torch::Tensor out = torch::empty({B, N, D}, opts);\n\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int threads1 = 256;\n fc1_silu_kernel<<<B * N * N, threads1, 0, stream>>>(\n nodes.data_ptr<float>(), pair_feats.data_ptr<float>(), w1.data_ptr<float>(), b1.data_ptr<float>(),\n hidden.data_ptr<float>(), B, N, D, P, H);\n\n int threads2 = 256;\n fc2_max_kernel<<<B * N * D, threads2, threads2 * sizeof(float), stream>>>(\n hidden.data_ptr<float>(), edge_mask.data_ptr<float>(), w2.data_ptr<float>(), b2.data_ptr<float>(),\n pooled.data_ptr<float>(), B, N, D, H);\n\n int threads3 = 128;\n layernorm_residual_kernel<<<B * N, threads3, threads3 * sizeof(float), stream>>>(\n nodes.data_ptr<float>(), pooled.data_ptr<float>(), ln_w.data_ptr<float>(), ln_b.data_ptr<float>(),\n out.data_ptr<float>(), B * N, D);\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"gf_vla_fused_pairwise_node_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"fused_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n with_cuda=True,\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, dim: int, pair_dim: int, hidden: int):\n super().__init__()\n self.dim = dim\n self.pair_dim = pair_dim\n self.hidden = hidden\n self.fuse = nn.Sequential(\n nn.Linear(2 * dim + pair_dim, hidden),\n nn.SiLU(),\n nn.Linear(hidden, dim),\n )\n self.out_norm = nn.LayerNorm(dim)\n\n def forward(self, nodes: torch.Tensor, pair_feats: torch.Tensor, edge_mask: torch.Tensor) -> torch.Tensor:\n return _ext.fused_forward(\n nodes.contiguous(),\n pair_feats.contiguous(),\n edge_mask.contiguous(),\n self.fuse[0].weight.contiguous(),\n self.fuse[0].bias.contiguous(),\n self.fuse[2].weight.contiguous(),\n self.fuse[2].bias.contiguous(),\n self.out_norm.weight.contiguous(),\n self.out_norm.bias.contiguous(),\n self.dim,\n self.pair_dim,\n self.hidden,\n )\n"
}
result ← submit_kernel (fail)
failsubmit_kernel
submit_kernel FAILED: kernel did not compile.
Error building extension 'gf_vla_fused_pairwise_node_ext': [1/3] /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=gf_vla_fused_pairwise_node_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/include/python3.10 -fPIC -std=c++17 -O3 -c /scratch/abaner/KernelBench/runs/l123_single_gpt/popcorn/gpt-5.5-priority/level_2_problem_10_cache/k_981bd6a10c5f/gf_vla_fused_pairwise_node_ext/main.cpp -o main.o
[2/3] /usr/local/cuda/bin/nvcc -MD -MF cuda.cuda.o.d -ccbin /opt/conda/bin/x86_64-conda-linux-gnu-cc -DTORCH_EXTENSION_NAME=gf_vla_fused_pairwise_node_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/include/python3.10 -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_BFLOAT16_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_90,code=compute_90 -gencode=arch=compute_90,code=sm_90 --compiler-options '-fPIC' -O3 -std=c++17 -c /scratch/abaner/KernelBench/runs/l123_single_gpt/popcorn/gpt-5.5-priority/level_2_problem_10_cache/k_981bd6a10c5f/gf_vla_fused_pairwise_node_ext/cuda.cu -o cuda.cuda.o
FAILED: [code=2] cuda.cuda.o
/usr/local/cuda/bin/nvcc -MD -MF cuda.cuda.o.d -ccbin /opt/conda/bin/x86_64-conda-linux-gnu-cc -DTORCH_EXTENSION_NAME=gf_vla_fused_pairwise_node_ext -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/abaner/KernelBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /opt/conda/include/python3.10 -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_BFLOAT16_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_90,code=compute_90 -gencode=arch=compute_90,code=sm_90 --compiler-options '-fPIC' -O3 -std=c++17 -c /scratch/abaner/KernelBench/runs/l123_single_gpt/popcorn/gpt-5.5-priority/level_2_problem_10_cache/k_981bd6a10c5f/gf_vla_fused_pairwise_node_ext/cuda.cu -o cuda.cuda.o
nvcc warning : incompatible redefinition for option 'compiler-bindir', the last value of this option was used
/scratch/abaner/KernelBench/runs/l123_single_gpt/popcorn/gpt-5.5-priority/level_2_problem_10_cache/k_981bd6a10c5f/gf_vla_fused_pairwise_node_ext/cuda.cu(145): error: namespace "at::cuda" has no member "getCurrentCUDAStream"
cudaStream_t stream = at::cuda::getCurrentCUDAStream();
^
1 error detected in the compilation of "/scratch/abaner/KernelBench/runs/l123_single_gpt/popcorn/gpt-5.5-priority/level_2_problem_10_cache/k_981bd6a10c5f/gf_vla_fused_pairwise_node_ext/cuda.cu".
ninja: build stopped: subcommand failed.
final submitted kernel (221 lines, 7,811 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
_cpp_src = r"""
#include <torch/extension.h>
torch::Tensor fused_forward(torch::Tensor nodes,
torch::Tensor pair_feats,
torch::Tensor edge_mask,
torch::Tensor w1,
torch::Tensor b1,
torch::Tensor w2,
torch::Tensor b2,
torch::Tensor ln_w,
torch::Tensor ln_b,
int64_t dim,
int64_t pair_dim,
int64_t hidden);
"""
_cuda_src = r"""
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cfloat>
__global__ void fc1_silu_kernel(const float* __restrict__ nodes,
const float* __restrict__ pair_feats,
const float* __restrict__ w1,
const float* __restrict__ b1,
float* __restrict__ hidden_out,
int B, int N, int D, int P, int H) {
int pair_idx = blockIdx.x;
int j = pair_idx % N;
int t = pair_idx / N;
int i = t % N;
int b = t / N;
int IN = 2 * D + P;
const float* ni = nodes + (b * N + i) * D;
const float* nj = nodes + (b * N + j) * D;
const float* pf = pair_feats + ((b * N + i) * N + j) * P;
float* hout = hidden_out + ((b * N + i) * N + j) * H;
for (int k = threadIdx.x; k < H; k += blockDim.x) {
const float* wk = w1 + k * IN;
float acc = b1[k];
#pragma unroll 4
for (int d = 0; d < D; ++d) acc = fmaf(ni[d], wk[d], acc);
#pragma unroll 4
for (int d = 0; d < D; ++d) acc = fmaf(nj[d], wk[D + d], acc);
#pragma unroll 4
for (int p = 0; p < P; ++p) acc = fmaf(pf[p], wk[2 * D + p], acc);
float sig = 1.0f / (1.0f + expf(-acc));
hout[k] = acc * sig;
}
}
__global__ void fc2_max_kernel(const float* __restrict__ hidden,
const float* __restrict__ edge_mask,
const float* __restrict__ w2,
const float* __restrict__ b2,
float* __restrict__ pooled,
int B, int N, int D, int H) {
extern __shared__ float sh[];
int idx = blockIdx.x;
int d = idx % D;
int row = idx / D; // b*N+i
int tid = threadIdx.x;
int b = row / N;
int i = row - b * N;
float maxv = -FLT_MAX;
const float* wd = w2 + d * H;
for (int j = 0; j < N; ++j) {
float m = edge_mask[(row * N) + j];
float part = 0.0f;
if (m >= 0.5f) {
const float* hptr = hidden + (row * N + j) * H;
for (int k = tid; k < H; k += blockDim.x) {
part = fmaf(hptr[k], wd[k], part);
}
}
sh[tid] = part;
__syncthreads();
for (int s = blockDim.x >> 1; s > 0; s >>= 1) {
if (tid < s) sh[tid] += sh[tid + s];
__syncthreads();
}
if (tid == 0 && m >= 0.5f) {
float val = sh[0] + b2[d];
maxv = fmaxf(maxv, val);
}
__syncthreads();
}
if (tid == 0) pooled[row * D + d] = maxv;
}
__global__ void layernorm_residual_kernel(const float* __restrict__ nodes,
const float* __restrict__ pooled,
const float* __restrict__ ln_w,
const float* __restrict__ ln_b,
float* __restrict__ out,
int rows, int D) {
extern __shared__ float sh[];
int row = blockIdx.x;
int tid = threadIdx.x;
float sum = 0.0f;
for (int d = tid; d < D; d += blockDim.x) sum += pooled[row * D + d];
sh[tid] = sum;
__syncthreads();
for (int s = blockDim.x >> 1; s > 0; s >>= 1) {
if (tid < s) sh[tid] += sh[tid + s];
__syncthreads();
}
float mean = sh[0] / (float)D;
float vsum = 0.0f;
for (int d = tid; d < D; d += blockDim.x) {
float x = pooled[row * D + d] - mean;
vsum = fmaf(x, x, vsum);
}
sh[tid] = vsum;
__syncthreads();
for (int s = blockDim.x >> 1; s > 0; s >>= 1) {
if (tid < s) sh[tid] += sh[tid + s];
__syncthreads();
}
float invstd = rsqrtf(sh[0] / (float)D + 1.0e-5f);
for (int d = tid; d < D; d += blockDim.x) {
int off = row * D + d;
float y = (pooled[off] - mean) * invstd;
out[off] = nodes[off] + y * ln_w[d] + ln_b[d];
}
}
torch::Tensor fused_forward(torch::Tensor nodes,
torch::Tensor pair_feats,
torch::Tensor edge_mask,
torch::Tensor w1,
torch::Tensor b1,
torch::Tensor w2,
torch::Tensor b2,
torch::Tensor ln_w,
torch::Tensor ln_b,
int64_t dim,
int64_t pair_dim,
int64_t hidden_size) {
int B = (int)nodes.size(0);
int N = (int)nodes.size(1);
int D = (int)dim;
int P = (int)pair_dim;
int H = (int)hidden_size;
auto opts = nodes.options();
torch::Tensor hidden = torch::empty({B, N, N, H}, opts);
torch::Tensor pooled = torch::empty({B, N, D}, opts);
torch::Tensor out = torch::empty({B, N, D}, opts);
cudaStream_t stream = at::cuda::getCurrentCUDAStream();
int threads1 = 256;
fc1_silu_kernel<<<B * N * N, threads1, 0, stream>>>(
nodes.data_ptr<float>(), pair_feats.data_ptr<float>(), w1.data_ptr<float>(), b1.data_ptr<float>(),
hidden.data_ptr<float>(), B, N, D, P, H);
int threads2 = 256;
fc2_max_kernel<<<B * N * D, threads2, threads2 * sizeof(float), stream>>>(
hidden.data_ptr<float>(), edge_mask.data_ptr<float>(), w2.data_ptr<float>(), b2.data_ptr<float>(),
pooled.data_ptr<float>(), B, N, D, H);
int threads3 = 128;
layernorm_residual_kernel<<<B * N, threads3, threads3 * sizeof(float), stream>>>(
nodes.data_ptr<float>(), pooled.data_ptr<float>(), ln_w.data_ptr<float>(), ln_b.data_ptr<float>(),
out.data_ptr<float>(), B * N, D);
return out;
}
"""
_ext = load_inline(
name="gf_vla_fused_pairwise_node_ext",
cpp_sources=_cpp_src,
cuda_sources=_cuda_src,
functions=["fused_forward"],
extra_cflags=["-O3"],
extra_cuda_cflags=["-O3"],
with_cuda=True,
verbose=False,
)
class ModelNew(nn.Module):
def __init__(self, dim: int, pair_dim: int, hidden: int):
super().__init__()
self.dim = dim
self.pair_dim = pair_dim
self.hidden = hidden
self.fuse = nn.Sequential(
nn.Linear(2 * dim + pair_dim, hidden),
nn.SiLU(),
nn.Linear(hidden, dim),
)
self.out_norm = nn.LayerNorm(dim)
def forward(self, nodes: torch.Tensor, pair_feats: torch.Tensor, edge_mask: torch.Tensor) -> torch.Tensor:
return _ext.fused_forward(
nodes.contiguous(),
pair_feats.contiguous(),
edge_mask.contiguous(),
self.fuse[0].weight.contiguous(),
self.fuse[0].bias.contiguous(),
self.fuse[2].weight.contiguous(),
self.fuse[2].bias.contiguous(),
self.out_norm.weight.contiguous(),
self.out_norm.bias.contiguous(),
self.dim,
self.pair_dim,
self.hidden,
)