call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp = r'''\n#include <torch/extension.h>\n#include <vector>\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out);\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z);\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y);\n\ntorch::Tensor rms_norm_cuda(torch::Tensor x, torch::Tensor weight) { auto out=torch::empty_like(x); rmsnorm_launcher(x,weight,out); return out; }\nstd::vector<torch::Tensor> conv_silu_z(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias) { auto B=xz.size(0),L=xz.size(1),I=xz.size(2)/2; auto xb=torch::empty({B,L,I},xz.options()); auto z=torch::empty({B,L,I},xz.options()); conv_silu_z_launcher(xz,weight,bias,xb,z); return {xb,z}; }\ntorch::Tensor selective_scan_gated(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D) { auto y=torch::empty_like(xb); scan_launcher(xb,z,delta_pre,Bt,Ct,A_log,D,y); return y; }\n'''\n\n_cuda = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n__device__ __forceinline__ float silu_f(float x) { return x / (1.0f + expf(-x)); }\n__device__ __forceinline__ float softplus_f(float x) { return (x > 20.0f) ? x : log1pf(expf(x)); }\n\n__global__ void rmsnorm_kernel(const float* __restrict__ x, const float* __restrict__ w, float* __restrict__ out, int rows, int D) {\n int row=blockIdx.x; if(row>=rows) return;\n float sum=0.0f; long long base=(long long)row*D;\n for(int d=threadIdx.x; d<D; d+=blockDim.x){ float v=x[base+d]; sum += v*v; }\n __shared__ float smem[256]; smem[threadIdx.x]=sum; __syncthreads();\n for(int s=blockDim.x/2; s>0; s>>=1){ if(threadIdx.x<s) smem[threadIdx.x]+=smem[threadIdx.x+s]; __syncthreads(); }\n float r=rsqrtf(smem[0]/(float)D + 1.1920928955078125e-7f);\n for(int d=threadIdx.x; d<D; d+=blockDim.x) out[base+d]=x[base+d]*r*w[d];\n}\n\n__global__ void conv_silu_z_kernel(const float* __restrict__ xz, const float* __restrict__ w, const float* __restrict__ bias, float* __restrict__ xb, float* __restrict__ z, int B, int L, int I, int K) {\n long long idx=(long long)blockIdx.x*blockDim.x+threadIdx.x; long long total=(long long)B*L*I; if(idx>=total) return;\n int i=idx%I; int t=(idx/I)%L; int b=idx/((long long)L*I); int twoI=I<<1; float acc=bias[i];\n #pragma unroll\n for(int k=0;k<4;++k){ int tt=t+k-(K-1); if(tt>=0 && tt<L && k<K) acc += xz[((long long)b*L+tt)*twoI+i] * w[(long long)i*K+k]; }\n xb[idx]=silu_f(acc); z[idx]=silu_f(xz[((long long)b*L+t)*twoI+I+i]);\n}\n\n__global__ void scan_shared_kernel(const float* __restrict__ xb, const float* __restrict__ z, const float* __restrict__ delta_pre, const float* __restrict__ Bt, const float* __restrict__ Ct, const float* __restrict__ A_log, const float* __restrict__ Dv, float* __restrict__ y, int B, int L, int I, int N) {\n __shared__ float Bs[16]; __shared__ float Cs[16];\n int b=blockIdx.y; int i=blockIdx.x*blockDim.x+threadIdx.x; bool valid=(i<I);\n float h[16]; float A[16];\n #pragma unroll\n for(int n=0;n<16;++n){ h[n]=0.0f; A[n]=(valid && n<N) ? -expf(A_log[(long long)i*N+n]) : 0.0f; }\n float Dval=valid ? Dv[i] : 0.0f;\n for(int t=0;t<L;++t){\n if(threadIdx.x<16){ Bs[threadIdx.x]=Bt[((long long)b*L+t)*N+threadIdx.x]; Cs[threadIdx.x]=Ct[((long long)b*L+t)*N+threadIdx.x]; }\n __syncthreads();\n if(valid){ long long xi=((long long)b*L+t)*I+i; float xval=xb[xi]; float delta=softplus_f(delta_pre[xi]); float xd=xval*delta; float sum=0.0f;\n #pragma unroll\n for(int n=0;n<16;++n){ float hv=expf(delta*A[n])*h[n]+xd*Bs[n]; h[n]=hv; sum += hv*Cs[n]; }\n y[xi]=(sum+xval*Dval)*z[xi]; }\n __syncthreads();\n }\n}\nvoid rmsnorm_launcher(torch::Tensor x, torch::Tensor weight, torch::Tensor out){ int rows=x.size(0)*x.size(1), D=x.size(2); rmsnorm_kernel<<<rows,256>>>(x.data_ptr<float>(),weight.data_ptr<float>(),out.data_ptr<float>(),rows,D); }\nvoid conv_silu_z_launcher(torch::Tensor xz, torch::Tensor weight, torch::Tensor bias, torch::Tensor xb, torch::Tensor z){ int B=xz.size(0),L=xz.size(1),I=xz.size(2)/2,K=weight.size(2); int threads=256; long long total=(long long)B*L*I; int blocks=(total+threads-1)/threads; conv_silu_z_kernel<<<blocks,threads>>>(xz.data_ptr<float>(),weight.data_ptr<float>(),bias.data_ptr<float>(),xb.data_ptr<float>(),z.data_ptr<float>(),B,L,I,K); }\nvoid scan_launcher(torch::Tensor xb, torch::Tensor z, torch::Tensor delta_pre, torch::Tensor Bt, torch::Tensor Ct, torch::Tensor A_log, torch::Tensor D, torch::Tensor y){ int B=xb.size(0),L=xb.size(1),I=xb.size(2),N=Bt.size(2); dim3 block(64); dim3 grid((I+63)/64,B); scan_shared_kernel<<<grid,block>>>(xb.data_ptr<float>(),z.data_ptr<float>(),delta_pre.data_ptr<float>(),Bt.data_ptr<float>(),Ct.data_ptr<float>(),A_log.data_ptr<float>(),D.data_ptr<float>(),y.data_ptr<float>(),B,L,I,N); }\n'''\n_ext=load_inline(name='mamba_block_ext_v3',cpp_sources=_cpp,cuda_sources=_cuda,functions=['rms_norm_cuda','conv_silu_z','selective_scan_gated'],extra_cflags=['-O3'],extra_cuda_cflags=['-O3'],verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self,d_model:int,d_state:int,d_conv:int,expand:int):\n super(ModelNew,self).__init__(); self.d_model=d_model; self.d_inner=d_model*expand; self.d_state=d_state; self.d_conv=d_conv\n self.norm=nn.RMSNorm(d_model); self.in_proj=nn.Linear(d_model,self.d_inner*2,bias=False); self.conv1d=nn.Conv1d(self.d_inner,self.d_inner,d_conv,padding=d_conv-1,groups=self.d_inner,bias=True); self.activation=nn.SiLU(); self.A_log=nn.Parameter(torch.randn(self.d_inner,d_state)); self.proj_B=nn.Linear(self.d_inner,d_state,bias=False); self.proj_C=nn.Linear(self.d_inner,d_state,bias=False); self.proj_delta=nn.Linear(self.d_inner,self.d_inner,bias=True); self.D=nn.Parameter(torch.ones(self.d_inner)); self.out_proj=nn.Linear(self.d_inner,d_model,bias=False)\n def forward(self,x:torch.Tensor)->torch.Tensor:\n residual=x; xn=_ext.rms_norm_cuda(x,self.norm.weight); xz=self.in_proj(xn); x_branch,z=_ext.conv_silu_z(xz,self.conv1d.weight,self.conv1d.bias); delta_pre=self.proj_delta(x_branch); B_t=self.proj_B(x_branch); C_t=self.proj_C(x_branch); y=_ext.selective_scan_gated(x_branch,z,delta_pre,B_t,C_t,self.A_log,self.D); return self.out_proj(y)+residual\n"
}