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_src = r'''\n#include <torch/extension.h>\ntorch::Tensor compute_dist_cuda(torch::Tensor x);\ntorch::Tensor approx_median_cuda(torch::Tensor dist);\ntorch::Tensor compute_phi_cuda(torch::Tensor x, torch::Tensor dist, torch::Tensor median);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math.h>\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be CUDA\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\n#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x)\nconstexpr int B1=2048; constexpr int B2=4096; constexpr float RANGE=256.0f;\n__global__ void dist_kernel(const float* __restrict__ x, float* __restrict__ dist, int N, int D){int j=blockIdx.x*blockDim.x+threadIdx.x;int i=blockIdx.y*blockDim.y+threadIdx.y;if(i<N&&j<N){float s=0.f;const float* xi=x+i*D;const float* xj=x+j*D;#pragma unroll\nfor(int d=0;d<32;++d){if(d<D){float diff=xj[d]-xi[d];s=fmaf(diff,diff,s);}}for(int d=32;d<D;++d){float diff=xj[d]-xi[d];s=fmaf(diff,diff,s);}dist[i*N+j]=s;}}\n__global__ void hist1_kernel(const float* __restrict__ data, int* __restrict__ hist, int n){extern __shared__ int sh[];for(int k=threadIdx.x;k<B1;k+=blockDim.x) sh[k]=0;__syncthreads();int tid=blockIdx.x*blockDim.x+threadIdx.x;int stride=blockDim.x*gridDim.x;float scale=(float)B1/RANGE;for(int idx=tid;idx<n;idx+=stride){float v=data[idx];int b=(int)(v*scale);if(b<0)b=0;if(b>=B1)b=B1-1;atomicAdd(&sh[b],1);}__syncthreads();for(int k=threadIdx.x;k<B1;k+=blockDim.x){int c=sh[k];if(c) atomicAdd(&hist[k],c);}}\n__global__ void find1_kernel(const int* __restrict__ hist, int* __restrict__ params, int rank){int cum=0;for(int b=0;b<B1;++b){int c=hist[b];if(cum+c>rank){params[0]=b;params[1]=cum;return;}cum+=c;}params[0]=B1-1;params[1]=cum-hist[B1-1];}\n__global__ void hist2_kernel(const float* __restrict__ data, int* __restrict__ hist, const int* __restrict__ params, int n){extern __shared__ int sh[];for(int k=threadIdx.x;k<B2;k+=blockDim.x) sh[k]=0;__syncthreads();int bin1=params[0];float lo=((float)bin1)*(RANGE/(float)B1);float width=RANGE/(float)B1;float scale=(float)B2/width;int tid=blockIdx.x*blockDim.x+threadIdx.x;int stride=blockDim.x*gridDim.x;for(int idx=tid;idx<n;idx+=stride){float v=data[idx];if(v>=lo && v<lo+width){int b=(int)((v-lo)*scale);if(b<0)b=0;if(b>=B2)b=B2-1;atomicAdd(&sh[b],1);}}__syncthreads();for(int k=threadIdx.x;k<B2;k+=blockDim.x){int c=sh[k];if(c) atomicAdd(&hist[k],c);}}\n__global__ void find2_kernel(const int* __restrict__ hist, const int* __restrict__ params, float* __restrict__ out, int rank){int target=rank-params[1];int cum=0;int b2=0;for(int b=0;b<B2;++b){int c=hist[b];if(cum+c>target){b2=b;break;}cum+=c;}float bin1=(float)params[0];float lo=bin1*(RANGE/(float)B1);float step=(RANGE/(float)B1)/(float)B2;out[0]=fmaxf(lo+((float)b2)*step,1.0e-5f);}\n__global__ void phi_kernel_d64(const float* __restrict__ x,const float* __restrict__ dist,const float* __restrict__ median,float* __restrict__ phi,int N,int D){extern __shared__ float sh[];int i=blockIdx.x;int t=threadIdx.x;float med=fmaxf(*median,1.0e-5f);float denom=fmaxf(logf((float)N),1.0f);float h=med/denom;float invh=1.0f/h;float a=invh-1.0f;float acc[64];#pragma unroll\nfor(int d=0;d<64;++d) acc[d]=0.f;const float* xi=x+i*D;for(int j=t;j<N;j+=blockDim.x){float k=__expf(-0.5f*dist[i*N+j]*invh);const float* xj=x+j*D;#pragma unroll\nfor(int d=0;d<64;++d){if(d<D) acc[d]+=k*(a*xj[d]-invh*xi[d]);}}for(int d=0;d<D;++d) sh[t*D+d]=acc[d];__syncthreads();for(int stride=blockDim.x>>1;stride>0;stride>>=1){if(t<stride){for(int d=0;d<D;++d) sh[t*D+d]+=sh[(t+stride)*D+d];}__syncthreads();}if(t==0){float invN=1.f/(float)N;for(int d=0;d<D;++d) phi[i*D+d]=sh[d]*invN;}}\n__global__ void phi_kernel_generic(const float* __restrict__ x,const float* __restrict__ dist,const float* __restrict__ median,float* __restrict__ phi,int N,int D){int idx=blockIdx.x*blockDim.x+threadIdx.x;int total=N*D;if(idx>=total)return;int d=idx%D;int i=idx/D;float med=fmaxf(*median,1e-5f);float invh=fmaxf(logf((float)N),1.f)/med;float a=invh-1.f;float xi=x[i*D+d];float sum=0.f;for(int j=0;j<N;++j){float k=__expf(-0.5f*dist[i*N+j]*invh);sum+=k*(a*x[j*D+d]-invh*xi);}phi[idx]=sum/(float)N;}\ntorch::Tensor compute_dist_cuda(torch::Tensor x){CHECK_INPUT(x);TORCH_CHECK(x.scalar_type()==at::kFloat,\"only float32 supported\");int N=(int)x.size(0),D=(int)x.size(1);auto dist=torch::empty({N,N},x.options());dim3 block(16,16);dim3 grid((N+15)/16,(N+15)/16);cudaStream_t s=at::cuda::getCurrentCUDAStream();dist_kernel<<<grid,block,0,s>>>(x.data_ptr<float>(),dist.data_ptr<float>(),N,D);C10_CUDA_KERNEL_LAUNCH_CHECK();return dist;}\ntorch::Tensor approx_median_cuda(torch::Tensor dist){CHECK_INPUT(dist);int n=(int)dist.numel();int rank=(n-1)/2;auto opts_i=torch::TensorOptions().dtype(torch::kInt32).device(dist.device());auto h1=torch::empty({B1},opts_i);auto h2=torch::empty({B2},opts_i);auto params=torch::empty({2},opts_i);auto out=torch::empty({},dist.options());cudaStream_t s=at::cuda::getCurrentCUDAStream();cudaMemsetAsync(h1.data_ptr<int>(),0,B1*sizeof(int),s);hist1_kernel<<<256,256,B1*sizeof(int),s>>>(dist.data_ptr<float>(),h1.data_ptr<int>(),n);find1_kernel<<<1,1,0,s>>>(h1.data_ptr<int>(),params.data_ptr<int>(),rank);cudaMemsetAsync(h2.data_ptr<int>(),0,B2*sizeof(int),s);hist2_kernel<<<256,256,B2*sizeof(int),s>>>(dist.data_ptr<float>(),h2.data_ptr<int>(),params.data_ptr<int>(),n);find2_kernel<<<1,1,0,s>>>(h2.data_ptr<int>(),params.data_ptr<int>(),out.data_ptr<float>(),rank);C10_CUDA_KERNEL_LAUNCH_CHECK();return out;}\ntorch::Tensor compute_phi_cuda(torch::Tensor x,torch::Tensor dist,torch::Tensor median){CHECK_INPUT(x);CHECK_INPUT(dist);CHECK_CUDA(median);int N=(int)x.size(0),D=(int)x.size(1);auto phi=torch::empty_like(x);cudaStream_t s=at::cuda::getCurrentCUDAStream();if(D<=64){int threads=128;phi_kernel_d64<<<N,threads,(size_t)threads*D*sizeof(float),s>>>(x.data_ptr<float>(),dist.data_ptr<float>(),median.data_ptr<float>(),phi.data_ptr<float>(),N,D);}else{int threads=128;int blocks=(N*D+threads-1)/threads;phi_kernel_generic<<<blocks,threads,0,s>>>(x.data_ptr<float>(),dist.data_ptr<float>(),median.data_ptr<float>(),phi.data_ptr<float>(),N,D);}C10_CUDA_KERNEL_LAUNCH_CHECK();return phi;}\n'''\n_svgd_ext=load_inline(name='svgd_ext_v2',cpp_sources=_cpp_src,cuda_sources=_cuda_src,functions=['compute_dist_cuda','approx_median_cuda','compute_phi_cuda'],extra_cuda_cflags=['-O3','--use_fast_math'],extra_cflags=['-O3'],verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, dim):\n super().__init__(); self.dim=dim; self.register_buffer('target_mean', torch.zeros(dim))\n def forward(self, particles: torch.Tensor) -> torch.Tensor:\n x=particles.contiguous(); dist=_svgd_ext.compute_dist_cuda(x); med=_svgd_ext.approx_median_cuda(dist); return _svgd_ext.compute_phi_cuda(x,dist,med)\n"
}