correct
40_SmithWatermanDPScore.py
started
2026-05-02T03:05:40Z
timingkernelbench.timing
kernel mean / median / std
0.03 / — / 3.62e-04 μs
ref mean / median / std
130.00 / — / 2.21 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
61456.00x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
warp stalls (top 5)nsight
reference PyTorch source (the prompt the agent sees)
import torch
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
"""
Differentiable Smith-Waterman-style local sequence alignment scoring.
Uses a soft-max relaxation of the DP recurrence so gradients can flow
through the alignment matrix.
"""
def __init__(self, gap_open=-1.0, temperature=1.0):
super().__init__()
self.gap_open = gap_open
self.temperature = temperature
def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:
"""
Args:
score_matrix: (B, M, N) – per-position similarity scores
Returns:
alignment_score: (B,) – soft local-alignment score (log-sum-exp over DP cells)
"""
B, M, N = score_matrix.shape
neg_inf = torch.tensor(float("-inf"), device=score_matrix.device, dtype=score_matrix.dtype)
# H[i][j] = max(0, H[i-1][j-1]+S[i][j], H[i-1][j]+gap, H[i][j-1]+gap)
H = score_matrix.new_full((B, M + 1, N + 1), 0.0)
for i in range(1, M + 1):
for j in range(1, N + 1):
match = H[:, i - 1, j - 1] + score_matrix[:, i - 1, j - 1]
delete = H[:, i - 1, j] + self.gap_open
insert = H[:, i, j - 1] + self.gap_open
zero = torch.zeros(B, device=score_matrix.device)
stack = torch.stack([zero, match, delete, insert], dim=-1)
H[:, i, j] = self.temperature * torch.logsumexp(stack / self.temperature, dim=-1)
return H.view(B, -1).max(dim=-1).values
seq_m = 32
seq_n = 32
batch_size = 16
def get_inputs():
return [torch.randn(popcorn_pri.jitter_int(batch_size), seq_m, seq_n)]
def get_init_inputs():
return []
turn 011.7s turn · 11.7s LLM · 0.0s tools
reasoning
**Optimizing code requirements**
I need to focus on crafting the code while optimizing certain parameters, like keeping B at 16 and M and N at 32. I’m thinking I should consider the gap_open and temperature arguments as well. Compiling the extension is also essential here. It's important that I use the right tools and gather the necessary specifications to make sure everything runs smoothly. I want to ensure I cover all bases!
call → get_gpu_specs
callget_gpu_specs
{}
result ← get_gpu_specs (ok)
okget_gpu_specs
GPU specs for NVIDIA H100 80GB HBM3:
total memory (runtime): 79.1 GB
spec entry: H100
GPU Architecture: Hopper
GPU Memory: 80GB
Memory Bandwidth: 3.35 TB/s
FP64 TFLOPS: 34
FP64 Tensor Core TFLOPS: 67
FP32 TFLOPS: 67
TF32 Tensor Core TFLOPS: 989 with sparsity
BFLOAT16 Tensore Core TFLOPS: 1979 with sparsity
FP16 Tensor Core TFLOPS: 1979 with sparsity
FP8 Tensor Core TFLOPS: 3958 with sparsity
INT8 Tensor Core TOPS: 3958 with sparsity
Register File Size: 64K 32-bit registers per SM
Maximum number of registers per thread: 255
Maximum number of thread blocks per SM: 32
Shared memory capacity per SM: 228 KB
Maximum shared memory per thread block: 227 KB
turn 157.2s turn · 57.2s LLM · 0.0s tools
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\n\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m1 = fmaxf(a, b);\n float m2 = fmaxf(c, d);\n float m = fmaxf(m1, m2);\n float invt = 1.0f / temp;\n float s = expf((a - m) * invt) + expf((b - m) * invt) + expf((c - m) * invt) + expf((d - m) * invt);\n return m + temp * logf(s);\n}\n\n__global__ void sw_kernel_f32(const float* __restrict__ score, float* __restrict__ out,\n int B, int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n int total = (M + 1) * (N + 1);\n extern __shared__ float H[];\n\n for (int idx = tid; idx < total; idx += blockDim.x) H[idx] = 0.0f;\n __syncthreads();\n\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n\n H[tid] = local_max;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) H[tid] = fmaxf(H[tid], H[tid + stride]);\n __syncthreads();\n }\n if (tid == 0) out[b] = H[0];\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0);\n int M = (int)score.size(1);\n int N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n int threads = 32;\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_f32<<<B, threads, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), B, M, N, gap_open, temperature);\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_v1', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 26.9s turn · 6.9s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\n\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m1 = fmaxf(a, b);\n float m2 = fmaxf(c, d);\n float m = fmaxf(m1, m2);\n float invt = 1.0f / temp;\n float s = expf((a - m) * invt) + expf((b - m) * invt) + expf((c - m) * invt) + expf((d - m) * invt);\n return m + temp * logf(s);\n}\n\n__global__ void sw_kernel_f32(const float* __restrict__ score, float* __restrict__ out,\n int B, int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n int total = (M + 1) * (N + 1);\n extern __shared__ float H[];\n\n for (int idx = tid; idx < total; idx += blockDim.x) H[idx] = 0.0f;\n __syncthreads();\n\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n\n H[tid] = local_max;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) H[tid] = fmaxf(H[tid], H[tid + stride]);\n __syncthreads();\n }\n if (tid == 0) out[b] = H[0];\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0);\n int M = (int)score.size(1);\n int N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n int threads = 32;\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_f32<<<B, threads, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), B, M, N, gap_open, temperature);\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_v1', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=3.81e-06 mean_abs_err=2.86e-07 max_rel_err=1.32e-07
turn 38.9s turn · 8.9s LLM · 0.0s tools
reasoning
**Considering performance optimization**
I’m thinking about how to improve performance, possibly by using submission methods to understand timing better. It feels like we have to be careful since we only have one chance to get it right. I wonder if optimizing for a fixed size, like 32, might help—maybe through unrolling or compiling constants. The host could dispatch specialized threads effectively, but I need to consider that kernel launch times could dominate, which might be a concern worth measuring.
call → static_check
callstatic_check
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\n\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m1 = fmaxf(a, b);\n float m2 = fmaxf(c, d);\n float m = fmaxf(m1, m2);\n float invt = 1.0f / temp;\n float s = expf((a - m) * invt) + expf((b - m) * invt) + expf((c - m) * invt) + expf((d - m) * invt);\n return m + temp * logf(s);\n}\n\n__global__ void sw_kernel_f32(const float* __restrict__ score, float* __restrict__ out,\n int B, int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n int total = (M + 1) * (N + 1);\n extern __shared__ float H[];\n\n for (int idx = tid; idx < total; idx += blockDim.x) H[idx] = 0.0f;\n __syncthreads();\n\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n\n H[tid] = local_max;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) H[tid] = fmaxf(H[tid], H[tid + stride]);\n __syncthreads();\n }\n if (tid == 0) out[b] = H[0];\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0);\n int M = (int)score.size(1);\n int N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n int threads = 32;\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_f32<<<B, threads, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), B, M, N, gap_open, temperature);\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_v1', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 415.4s turn · 15.4s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float lse4_one(float b, float c, float d) {\n float m = fmaxf(0.0f, fmaxf(b, fmaxf(c, d)));\n float s = expf(-m) + expf(b - m) + expf(c - m) + expf(d - m);\n return m + logf(s);\n}\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n float invt = 1.0f / temp;\n float s = expf((a-m)*invt) + expf((b-m)*invt) + expf((c-m)*invt) + expf((d-m)*invt);\n return m + temp * logf(s);\n}\n\n__global__ void sw_kernel_32_t1(const float* __restrict__ score, float* __restrict__ out, float gap_open) {\n const int b = blockIdx.x;\n const int tid = threadIdx.x;\n extern __shared__ float H[];\n for (int idx = tid; idx < 1089; idx += 32) H[idx] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * 1024;\n #pragma unroll 1\n for (int diag = 2; diag <= 64; ++diag) {\n int i_min = max(1, diag - 32);\n int i_max = min(32, diag - 1);\n int count = i_max - i_min + 1;\n if (tid < count) {\n int i = i_min + tid;\n int j = diag - i;\n float match = H[(i - 1) * 33 + (j - 1)] + S[(i - 1) * 32 + (j - 1)];\n float del = H[(i - 1) * 33 + j] + gap_open;\n float ins = H[i * 33 + (j - 1)] + gap_open;\n float v = lse4_one(match, del, ins);\n H[i * 33 + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n H[tid] = local_max;\n __syncthreads();\n for (int stride = 16; stride > 0; stride >>= 1) {\n if (tid < stride) H[tid] = fmaxf(H[tid], H[tid + stride]);\n __syncthreads();\n }\n if (tid == 0) out[b] = H[0];\n}\n\n__global__ void sw_kernel_generic(const float* __restrict__ score, float* __restrict__ out,\n int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n int total = (M + 1) * (N + 1);\n extern __shared__ float H[];\n for (int idx = tid; idx < total; idx += blockDim.x) H[idx] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n H[tid] = local_max;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) H[tid] = fmaxf(H[tid], H[tid + stride]);\n __syncthreads();\n }\n if (tid == 0) out[b] = H[0];\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0), M = (int)score.size(1), N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n if (M == 32 && N == 32 && temperature == 1.0f) {\n sw_kernel_32_t1<<<B, 32, 1089 * sizeof(float)>>>(score.data_ptr<float>(), out.data_ptr<float>(), gap_open);\n } else {\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_generic<<<B, 32, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), M, N, gap_open, temperature);\n }\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_v2', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=3.81e-06 mean_abs_err=1.12e-06 max_rel_err=1.34e-07
turn 5 · 1 tool call(s) · 16.3s turn · 16.3s LLM · 7,038 chars (click to expand)
turn 516.3s turn · 16.3s LLM · 0.0s tools
reasoning
**Deciding on implementation options**
I’m considering my approach and wondering if using fast math can speed things up. I might look into warp shuffle reduction without needing syncthreads, but I’ll need to ensure synchronization per diagonal. I think I can use __shfl_down_sync to reduce local maxes without shared memory.
It seems initializing the entire H loop with 1089 writes could be heavy, so I could skip some initializations, focusing only on the necessary borders. I just want to improve efficiency.
**Exploring warp shuffle for reduction**
I'm thinking about whether computing the local max can be improved using warp shuffle, especially since my block dimension is 32. I could utilize __shfl_down_sync, which might help me eliminate the final writes to H. I’m unsure if I need to call __syncthreads after the last diagonal since the last loop syncthreads could cover it. I should consider using warp reduction for version three. I’ll check on that!
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float lse4_one(float b, float c, float d) {\n float m = fmaxf(0.0f, fmaxf(b, fmaxf(c, d)));\n float s = expf(-m) + expf(b - m) + expf(c - m) + expf(d - m);\n return m + logf(s);\n}\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n float invt = 1.0f / temp;\n float s = expf((a-m)*invt) + expf((b-m)*invt) + expf((c-m)*invt) + expf((d-m)*invt);\n return m + temp * logf(s);\n}\n\n__device__ __forceinline__ float warp_max(float v) {\n unsigned mask = 0xffffffffu;\n v = fmaxf(v, __shfl_down_sync(mask, v, 16));\n v = fmaxf(v, __shfl_down_sync(mask, v, 8));\n v = fmaxf(v, __shfl_down_sync(mask, v, 4));\n v = fmaxf(v, __shfl_down_sync(mask, v, 2));\n v = fmaxf(v, __shfl_down_sync(mask, v, 1));\n return v;\n}\n\n__global__ void sw_kernel_32_t1(const float* __restrict__ score, float* __restrict__ out, float gap_open) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n extern __shared__ float H[];\n if (tid < 33) H[tid] = 0.0f;\n if (tid < 32) H[(tid + 1) * 33] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * 1024;\n #pragma unroll 1\n for (int diag = 2; diag <= 64; ++diag) {\n int i_min = max(1, diag - 32);\n int i_max = min(32, diag - 1);\n int count = i_max - i_min + 1;\n if (tid < count) {\n int i = i_min + tid;\n int j = diag - i;\n float match = H[(i - 1) * 33 + (j - 1)] + S[(i - 1) * 32 + (j - 1)];\n float del = H[(i - 1) * 33 + j] + gap_open;\n float ins = H[i * 33 + (j - 1)] + gap_open;\n float v = lse4_one(match, del, ins);\n H[i * 33 + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\n__global__ void sw_kernel_generic(const float* __restrict__ score, float* __restrict__ out,\n int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n extern __shared__ float H[];\n for (int j = tid; j <= N; j += blockDim.x) H[j] = 0.0f;\n for (int i = tid + 1; i <= M; i += blockDim.x) H[i * W] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0), M = (int)score.size(1), N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n if (M == 32 && N == 32 && temperature == 1.0f) {\n sw_kernel_32_t1<<<B, 32, 1089 * sizeof(float)>>>(score.data_ptr<float>(), out.data_ptr<float>(), gap_open);\n } else {\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_generic<<<B, 32, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), M, N, gap_open, temperature);\n }\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_v3', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=3.81e-06 mean_abs_err=1.12e-06 max_rel_err=1.34e-07
turn 626.2s turn · 26.2s LLM · 0.0s tools
call → static_check
callstatic_check
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float lse4_one(float b, float c, float d) {\n float m = fmaxf(0.0f, fmaxf(b, fmaxf(c, d)));\n float s = expf(-m) + expf(b - m) + expf(c - m) + expf(d - m);\n return m + logf(s);\n}\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n float invt = 1.0f / temp;\n float s = expf((a-m)*invt) + expf((b-m)*invt) + expf((c-m)*invt) + expf((d-m)*invt);\n return m + temp * logf(s);\n}\n\n__device__ __forceinline__ float warp_max(float v) {\n unsigned mask = 0xffffffffu;\n v = fmaxf(v, __shfl_down_sync(mask, v, 16));\n v = fmaxf(v, __shfl_down_sync(mask, v, 8));\n v = fmaxf(v, __shfl_down_sync(mask, v, 4));\n v = fmaxf(v, __shfl_down_sync(mask, v, 2));\n v = fmaxf(v, __shfl_down_sync(mask, v, 1));\n return v;\n}\n\n__global__ void sw_kernel_32_t1(const float* __restrict__ score, float* __restrict__ out, float gap_open) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n extern __shared__ float H[];\n if (tid == 0) H[32] = 0.0f;\n H[tid] = 0.0f;\n H[(tid + 1) * 33] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * 1024;\n #pragma unroll 1\n for (int diag = 2; diag <= 64; ++diag) {\n int i_min = max(1, diag - 32);\n int i_max = min(32, diag - 1);\n int count = i_max - i_min + 1;\n if (tid < count) {\n int i = i_min + tid;\n int j = diag - i;\n float match = H[(i - 1) * 33 + (j - 1)] + S[(i - 1) * 32 + (j - 1)];\n float del = H[(i - 1) * 33 + j] + gap_open;\n float ins = H[i * 33 + (j - 1)] + gap_open;\n float v = lse4_one(match, del, ins);\n H[i * 33 + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\n__global__ void sw_kernel_generic(const float* __restrict__ score, float* __restrict__ out,\n int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n extern __shared__ float H[];\n for (int j = tid; j <= N; j += blockDim.x) H[j] = 0.0f;\n for (int i = tid + 1; i <= M; i += blockDim.x) H[i * W] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0), M = (int)score.size(1), N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n if (M == 32 && N == 32 && temperature == 1.0f) {\n sw_kernel_32_t1<<<B, 32, 1089 * sizeof(float)>>>(score.data_ptr<float>(), out.data_ptr<float>(), gap_open);\n } else {\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_generic<<<B, 32, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), M, N, gap_open, temperature);\n }\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_final', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 7 · 1 tool call(s) · 13.8s turn · 13.8s LLM · 6,573 chars (click to expand)
turn 713.8s turn · 13.8s LLM · 0.0s tools
reasoning
**Clarifying compilation issues**
I’m thinking about whether I need to ensure everything is correct after making a fix. We haven’t run any tests yet, and it seems like I might just be compiling statically right now. I’m not sure if static only compiles correctly, so I may need to submit it again to see if it’ll compile. However, I’m also considering adding H[tid], even though I'm not sure if it's okay for tid values between 0 and 31. It makes me wonder about correctness at this point too.
call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float lse4_one(float b, float c, float d) {\n float m = fmaxf(0.0f, fmaxf(b, fmaxf(c, d)));\n float s = expf(-m) + expf(b - m) + expf(c - m) + expf(d - m);\n return m + logf(s);\n}\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n float invt = 1.0f / temp;\n float s = expf((a-m)*invt) + expf((b-m)*invt) + expf((c-m)*invt) + expf((d-m)*invt);\n return m + temp * logf(s);\n}\n\n__device__ __forceinline__ float warp_max(float v) {\n unsigned mask = 0xffffffffu;\n v = fmaxf(v, __shfl_down_sync(mask, v, 16));\n v = fmaxf(v, __shfl_down_sync(mask, v, 8));\n v = fmaxf(v, __shfl_down_sync(mask, v, 4));\n v = fmaxf(v, __shfl_down_sync(mask, v, 2));\n v = fmaxf(v, __shfl_down_sync(mask, v, 1));\n return v;\n}\n\n__global__ void sw_kernel_32_t1(const float* __restrict__ score, float* __restrict__ out, float gap_open) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n extern __shared__ float H[];\n if (tid == 0) H[32] = 0.0f;\n H[tid] = 0.0f;\n H[(tid + 1) * 33] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * 1024;\n #pragma unroll 1\n for (int diag = 2; diag <= 64; ++diag) {\n int i_min = max(1, diag - 32);\n int i_max = min(32, diag - 1);\n int count = i_max - i_min + 1;\n if (tid < count) {\n int i = i_min + tid;\n int j = diag - i;\n float match = H[(i - 1) * 33 + (j - 1)] + S[(i - 1) * 32 + (j - 1)];\n float del = H[(i - 1) * 33 + j] + gap_open;\n float ins = H[i * 33 + (j - 1)] + gap_open;\n float v = lse4_one(match, del, ins);\n H[i * 33 + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\n__global__ void sw_kernel_generic(const float* __restrict__ score, float* __restrict__ out,\n int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n extern __shared__ float H[];\n for (int j = tid; j <= N; j += blockDim.x) H[j] = 0.0f;\n for (int i = tid + 1; i <= M; i += blockDim.x) H[i * W] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0), M = (int)score.size(1), N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n if (M == 32 && N == 32 && temperature == 1.0f) {\n sw_kernel_32_t1<<<B, 32, 1089 * sizeof(float)>>>(score.data_ptr<float>(), out.data_ptr<float>(), gap_open);\n } else {\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_generic<<<B, 32, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), M, N, gap_open, temperature);\n }\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_final', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=3.81e-06 mean_abs_err=1.12e-06 max_rel_err=1.34e-07
turn 8 · FINAL · 1 tool call(s) · 12.6s turn · 12.6s LLM · 6,846 chars (click to expand)
turn 812.6s turn · 12.6s LLM · 0.0s tools · FINAL
reasoning
**Finalizing code submission**
I need to focus on submitting the final code. I’m pondering if there's room for further optimization, but timing is limited. It’s essential to ensure there’s no issue with the fallback for cases where temperature isn’t equal to 1; default constructor arguments could help here. Using `score.contiguous()` seems like a solution if inputs aren’t contiguous. I’ll stick with an exact check for `temp == 1`, and then I need to call `submit_kernel`.
call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_sources = r'''\n#include <torch/extension.h>\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);\ntorch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {\n return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);\n}\n'''\n\ncuda_sources = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__device__ __forceinline__ float lse4_one(float b, float c, float d) {\n float m = fmaxf(0.0f, fmaxf(b, fmaxf(c, d)));\n float s = expf(-m) + expf(b - m) + expf(c - m) + expf(d - m);\n return m + logf(s);\n}\n\n__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {\n float m = fmaxf(fmaxf(a, b), fmaxf(c, d));\n float invt = 1.0f / temp;\n float s = expf((a-m)*invt) + expf((b-m)*invt) + expf((c-m)*invt) + expf((d-m)*invt);\n return m + temp * logf(s);\n}\n\n__device__ __forceinline__ float warp_max(float v) {\n unsigned mask = 0xffffffffu;\n v = fmaxf(v, __shfl_down_sync(mask, v, 16));\n v = fmaxf(v, __shfl_down_sync(mask, v, 8));\n v = fmaxf(v, __shfl_down_sync(mask, v, 4));\n v = fmaxf(v, __shfl_down_sync(mask, v, 2));\n v = fmaxf(v, __shfl_down_sync(mask, v, 1));\n return v;\n}\n\n__global__ void sw_kernel_32_t1(const float* __restrict__ score, float* __restrict__ out, float gap_open) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n extern __shared__ float H[];\n if (tid == 0) H[32] = 0.0f;\n H[tid] = 0.0f;\n H[(tid + 1) * 33] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * 1024;\n #pragma unroll 1\n for (int diag = 2; diag <= 64; ++diag) {\n int i_min = max(1, diag - 32);\n int i_max = min(32, diag - 1);\n int count = i_max - i_min + 1;\n if (tid < count) {\n int i = i_min + tid;\n int j = diag - i;\n float match = H[(i - 1) * 33 + (j - 1)] + S[(i - 1) * 32 + (j - 1)];\n float del = H[(i - 1) * 33 + j] + gap_open;\n float ins = H[i * 33 + (j - 1)] + gap_open;\n float v = lse4_one(match, del, ins);\n H[i * 33 + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\n__global__ void sw_kernel_generic(const float* __restrict__ score, float* __restrict__ out,\n int M, int N, float gap_open, float temperature) {\n int b = blockIdx.x;\n int tid = threadIdx.x;\n int W = N + 1;\n extern __shared__ float H[];\n for (int j = tid; j <= N; j += blockDim.x) H[j] = 0.0f;\n for (int i = tid + 1; i <= M; i += blockDim.x) H[i * W] = 0.0f;\n __syncthreads();\n float local_max = 0.0f;\n const float* S = score + ((long long)b) * M * N;\n for (int diag = 2; diag <= M + N; ++diag) {\n int i_min = max(1, diag - N);\n int i_max = min(M, diag - 1);\n int count = i_max - i_min + 1;\n for (int t = tid; t < count; t += blockDim.x) {\n int i = i_min + t;\n int j = diag - i;\n float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];\n float del = H[(i - 1) * W + j] + gap_open;\n float ins = H[i * W + (j - 1)] + gap_open;\n float v = lse4_temp(0.0f, match, del, ins, temperature);\n H[i * W + j] = v;\n local_max = fmaxf(local_max, v);\n }\n __syncthreads();\n }\n local_max = warp_max(local_max);\n if (tid == 0) out[b] = local_max;\n}\n\ntorch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {\n TORCH_CHECK(score.is_cuda(), \"score must be CUDA\");\n TORCH_CHECK(score.scalar_type() == torch::kFloat32, \"score must be float32\");\n int B = (int)score.size(0), M = (int)score.size(1), N = (int)score.size(2);\n auto out = torch::empty({B}, score.options());\n if (M == 32 && N == 32 && temperature == 1.0f) {\n sw_kernel_32_t1<<<B, 32, 1089 * sizeof(float)>>>(score.data_ptr<float>(), out.data_ptr<float>(), gap_open);\n } else {\n size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);\n sw_kernel_generic<<<B, 32, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), M, N, gap_open, temperature);\n }\n return out;\n}\n'''\n\n_ext = load_inline(name='sw_softalign_ext_final', cpp_sources=cpp_sources, cuda_sources=cuda_sources,\n functions=['sw_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, gap_open=-1.0, temperature=1.0):\n super().__init__()\n self.gap_open = gap_open\n self.temperature = temperature\n def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:\n return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))\n"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 0.03 μs
Runtime stats: mean=0.03μs median=?μs std=0.00μs
Numerical precision: max_abs_err=3.81e-06 mean_abs_err=1.12e-06 max_rel_err=1.34e-07
Memory: 33.06 MB peak (ref: 33.13 MB, ratio: 0.9978x)
Kernel launches: 1 (ref: 61456, fusion ratio: 61456.0)
SOL score: 0.0007
Flagged for excessive speedup — this submission may have been rejected by automated review.
final submitted kernel (128 lines, 4,970 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
cpp_sources = r'''
#include <torch/extension.h>
torch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature);
torch::Tensor sw_forward(torch::Tensor score, double gap_open, double temperature) {
return sw_forward_cuda(score.contiguous(), (float)gap_open, (float)temperature);
}
'''
cuda_sources = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
__device__ __forceinline__ float lse4_one(float b, float c, float d) {
float m = fmaxf(0.0f, fmaxf(b, fmaxf(c, d)));
float s = expf(-m) + expf(b - m) + expf(c - m) + expf(d - m);
return m + logf(s);
}
__device__ __forceinline__ float lse4_temp(float a, float b, float c, float d, float temp) {
float m = fmaxf(fmaxf(a, b), fmaxf(c, d));
float invt = 1.0f / temp;
float s = expf((a-m)*invt) + expf((b-m)*invt) + expf((c-m)*invt) + expf((d-m)*invt);
return m + temp * logf(s);
}
__device__ __forceinline__ float warp_max(float v) {
unsigned mask = 0xffffffffu;
v = fmaxf(v, __shfl_down_sync(mask, v, 16));
v = fmaxf(v, __shfl_down_sync(mask, v, 8));
v = fmaxf(v, __shfl_down_sync(mask, v, 4));
v = fmaxf(v, __shfl_down_sync(mask, v, 2));
v = fmaxf(v, __shfl_down_sync(mask, v, 1));
return v;
}
__global__ void sw_kernel_32_t1(const float* __restrict__ score, float* __restrict__ out, float gap_open) {
int b = blockIdx.x;
int tid = threadIdx.x;
extern __shared__ float H[];
if (tid == 0) H[32] = 0.0f;
H[tid] = 0.0f;
H[(tid + 1) * 33] = 0.0f;
__syncthreads();
float local_max = 0.0f;
const float* S = score + ((long long)b) * 1024;
#pragma unroll 1
for (int diag = 2; diag <= 64; ++diag) {
int i_min = max(1, diag - 32);
int i_max = min(32, diag - 1);
int count = i_max - i_min + 1;
if (tid < count) {
int i = i_min + tid;
int j = diag - i;
float match = H[(i - 1) * 33 + (j - 1)] + S[(i - 1) * 32 + (j - 1)];
float del = H[(i - 1) * 33 + j] + gap_open;
float ins = H[i * 33 + (j - 1)] + gap_open;
float v = lse4_one(match, del, ins);
H[i * 33 + j] = v;
local_max = fmaxf(local_max, v);
}
__syncthreads();
}
local_max = warp_max(local_max);
if (tid == 0) out[b] = local_max;
}
__global__ void sw_kernel_generic(const float* __restrict__ score, float* __restrict__ out,
int M, int N, float gap_open, float temperature) {
int b = blockIdx.x;
int tid = threadIdx.x;
int W = N + 1;
extern __shared__ float H[];
for (int j = tid; j <= N; j += blockDim.x) H[j] = 0.0f;
for (int i = tid + 1; i <= M; i += blockDim.x) H[i * W] = 0.0f;
__syncthreads();
float local_max = 0.0f;
const float* S = score + ((long long)b) * M * N;
for (int diag = 2; diag <= M + N; ++diag) {
int i_min = max(1, diag - N);
int i_max = min(M, diag - 1);
int count = i_max - i_min + 1;
for (int t = tid; t < count; t += blockDim.x) {
int i = i_min + t;
int j = diag - i;
float match = H[(i - 1) * W + (j - 1)] + S[(i - 1) * N + (j - 1)];
float del = H[(i - 1) * W + j] + gap_open;
float ins = H[i * W + (j - 1)] + gap_open;
float v = lse4_temp(0.0f, match, del, ins, temperature);
H[i * W + j] = v;
local_max = fmaxf(local_max, v);
}
__syncthreads();
}
local_max = warp_max(local_max);
if (tid == 0) out[b] = local_max;
}
torch::Tensor sw_forward_cuda(torch::Tensor score, float gap_open, float temperature) {
TORCH_CHECK(score.is_cuda(), "score must be CUDA");
TORCH_CHECK(score.scalar_type() == torch::kFloat32, "score must be float32");
int B = (int)score.size(0), M = (int)score.size(1), N = (int)score.size(2);
auto out = torch::empty({B}, score.options());
if (M == 32 && N == 32 && temperature == 1.0f) {
sw_kernel_32_t1<<<B, 32, 1089 * sizeof(float)>>>(score.data_ptr<float>(), out.data_ptr<float>(), gap_open);
} else {
size_t shmem = (size_t)(M + 1) * (N + 1) * sizeof(float);
sw_kernel_generic<<<B, 32, shmem>>>(score.data_ptr<float>(), out.data_ptr<float>(), M, N, gap_open, temperature);
}
return out;
}
'''
_ext = load_inline(name='sw_softalign_ext_final', cpp_sources=cpp_sources, cuda_sources=cuda_sources,
functions=['sw_forward'], extra_cuda_cflags=['-O3','--use_fast_math'], verbose=False)
class ModelNew(nn.Module):
def __init__(self, gap_open=-1.0, temperature=1.0):
super().__init__()
self.gap_open = gap_open
self.temperature = temperature
def forward(self, score_matrix: torch.Tensor) -> torch.Tensor:
return _ext.sw_forward(score_matrix, float(self.gap_open), float(self.temperature))