call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor triplet_forward_cuda(torch::Tensor anchor, torch::Tensor positive, torch::Tensor negative, double margin);\n\ntorch::Tensor triplet_forward(torch::Tensor anchor, torch::Tensor positive, torch::Tensor negative, double margin) {\n return triplet_forward_cuda(anchor, positive, negative, margin);\n}\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\n#define THREADS 256\n\n__global__ void triplet_kernel_vec(\n const float* __restrict__ anchor,\n const float* __restrict__ positive,\n const float* __restrict__ negative,\n double* __restrict__ sum_out,\n int64_t N,\n int64_t D,\n float margin)\n{\n const int row = blockIdx.x;\n const int tid = threadIdx.x;\n if (row >= N) return;\n\n float acc_ap = 0.0f;\n float acc_an = 0.0f;\n const float eps = 1.0e-6f;\n const int64_t base = (int64_t)row * D;\n\n if ((D & 3) == 0) {\n const int64_t D4 = D >> 2;\n const float4* __restrict__ a4 = reinterpret_cast<const float4*>(anchor + base);\n const float4* __restrict__ p4 = reinterpret_cast<const float4*>(positive + base);\n const float4* __restrict__ n4 = reinterpret_cast<const float4*>(negative + base);\n\n for (int64_t j = tid; j < D4; j += THREADS) {\n float4 av = a4[j];\n float4 pv = p4[j];\n float4 nv = n4[j];\n\n float d0 = av.x - pv.x + eps;\n float e0 = av.x - nv.x + eps;\n acc_ap = fmaf(d0, d0, acc_ap);\n acc_an = fmaf(e0, e0, acc_an);\n\n float d1 = av.y - pv.y + eps;\n float e1 = av.y - nv.y + eps;\n acc_ap = fmaf(d1, d1, acc_ap);\n acc_an = fmaf(e1, e1, acc_an);\n\n float d2 = av.z - pv.z + eps;\n float e2 = av.z - nv.z + eps;\n acc_ap = fmaf(d2, d2, acc_ap);\n acc_an = fmaf(e2, e2, acc_an);\n\n float d3 = av.w - pv.w + eps;\n float e3 = av.w - nv.w + eps;\n acc_ap = fmaf(d3, d3, acc_ap);\n acc_an = fmaf(e3, e3, acc_an);\n }\n } else {\n for (int64_t j = tid; j < D; j += THREADS) {\n float av = anchor[base + j];\n float d = av - positive[base + j] + eps;\n float e = av - negative[base + j] + eps;\n acc_ap = fmaf(d, d, acc_ap);\n acc_an = fmaf(e, e, acc_an);\n }\n }\n\n __shared__ float sh_ap[THREADS];\n __shared__ float sh_an[THREADS];\n sh_ap[tid] = acc_ap;\n sh_an[tid] = acc_an;\n __syncthreads();\n\n for (int stride = THREADS / 2; stride >= 32; stride >>= 1) {\n if (tid < stride) {\n sh_ap[tid] += sh_ap[tid + stride];\n sh_an[tid] += sh_an[tid + stride];\n }\n __syncthreads();\n }\n\n if (tid < 32) {\n float v_ap = sh_ap[tid];\n float v_an = sh_an[tid];\n unsigned mask = 0xffffffffu;\n v_ap += __shfl_down_sync(mask, v_ap, 16);\n v_an += __shfl_down_sync(mask, v_an, 16);\n v_ap += __shfl_down_sync(mask, v_ap, 8);\n v_an += __shfl_down_sync(mask, v_an, 8);\n v_ap += __shfl_down_sync(mask, v_ap, 4);\n v_an += __shfl_down_sync(mask, v_an, 4);\n v_ap += __shfl_down_sync(mask, v_ap, 2);\n v_an += __shfl_down_sync(mask, v_an, 2);\n v_ap += __shfl_down_sync(mask, v_ap, 1);\n v_an += __shfl_down_sync(mask, v_an, 1);\n\n if (tid == 0) {\n float loss = sqrtf(v_ap) - sqrtf(v_an) + margin;\n if (loss > 0.0f) atomicAdd(sum_out, (double)loss);\n }\n }\n}\n\n__global__ void finalize_kernel(const double* __restrict__ sum_in, float* __restrict__ out, int64_t N) {\n out[0] = (float)(sum_in[0] / (double)N);\n}\n\ntorch::Tensor triplet_forward_cuda(torch::Tensor anchor, torch::Tensor positive, torch::Tensor negative, double margin) {\n const int64_t N = anchor.size(0);\n const int64_t D = anchor.numel() / N;\n\n auto sum_opts = anchor.options().dtype(torch::kFloat64);\n torch::Tensor sum = torch::zeros({}, sum_opts);\n torch::Tensor out = torch::empty({}, anchor.options());\n\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n dim3 block(THREADS);\n dim3 grid((unsigned int)N);\n\n triplet_kernel_vec<<<grid, block, 0, stream>>>(\n anchor.data_ptr<float>(),\n positive.data_ptr<float>(),\n negative.data_ptr<float>(),\n sum.data_ptr<double>(),\n N, D, (float)margin);\n\n finalize_kernel<<<1, 1, 0, stream>>>(sum.data_ptr<double>(), out.data_ptr<float>(), N);\n return out;\n}\n\"\"\"\n\n_triplet_ext = load_inline(\n name=\"triplet_margin_loss_inline_ext\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"triplet_forward\"],\n extra_cflags=[\"-O3\"],\n extra_cuda_cflags=[\"-O3\"],\n with_cuda=True,\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, margin=1.0):\n super(ModelNew, self).__init__()\n self.margin = float(margin)\n\n def forward(self, anchor, positive, negative):\n return _triplet_ext.triplet_forward(anchor, positive, negative, self.margin)\n"
}