ワンクリックで
cpu-basics
CPU C++ 算子核心概念、标准结构模式、KernelBench 代码规范和内嵌扩展方法
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
CPU C++ 算子核心概念、标准结构模式、KernelBench 代码规范和内嵌扩展方法
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
AscendC direct-invoke 崩溃/挂起修复索引:Kernel timeout、hang、Segmentation Fault、aic error、buffer 死锁、plog/memcheck 调试。
AscendC direct-invoke 精度失败修复索引:输出全 0/随机值、DataCopy 对齐、EnQue/DeQue 同步、FP16/FP32 精度、Cast RoundMode、DumpTensor 分段定位。
AscendC direct-invoke 工程契约:WA 使用 kernel.py + ascendc_op/,ModelNew 调用 torch.ops.npu.*,adapter 负责复制工程、CMake 构建和 npu-arch patch。适用于 dsl=ascendc 的 autoresearch 任务。
把注册式 AscendC 算子迁移为 direct-invoke 工程的保真原则:kernel 算法和 tiling 公式不乱改,只替换注册框架胶水、入口 ABI、host launch 与 PyTorch extension。
CATLASS TileShape 与 on-chip 缓存容量约束:L1/L0A/L0B/L0C 预算公式、fp16/fp32 Pingpong 双缓冲、512B 对齐与排布对 Tile 选型的影响。调参前必读。
CATLASS Gemm 性能调优:DispatchPolicy、Tile 与分核负载均衡、Swizzle、何时用 padding/Split-K/Preload。面向 AR 修改 catlass_kernel.asc 中的类型别名。
| name | cpu-basics |
| description | CPU C++ 算子核心概念、标准结构模式、KernelBench 代码规范和内嵌扩展方法 |
| category | fundamental |
| version | 1.0.0 |
| metadata | {"backend":"cpu","dsl":"cpp","operator_patterns":"all","architecture":"x86_64, aarch64"} |
PYBIND11_MODULE 注册的 C++ 函数,编译后在 CPU 上执行load_inline 动态编译加载所有 CPU C++ 内核都遵循相同的五步结构模式:
torch::Tensor standard_kernel(torch::Tensor x) {
// 1. 确保输入张量是连续的
if (!x.is_contiguous()) {
x = x.contiguous();
}
// 2. 检查数据类型,支持多种类型
torch::ScalarType dtype = x.scalar_type();
bool need_convert = (dtype != torch::kFloat32 && dtype != torch::kFloat64 &&
dtype != torch::kInt32 && dtype != torch::kInt64);
torch::Tensor input = need_convert ? x.to(torch::kFloat32) : x;
// 3. 创建输出张量
torch::Tensor output = torch::zeros_like(input);
// 4. 根据数据类型分发计算
if (input.scalar_type() == torch::kFloat32) {
auto x_ptr = input.data_ptr<float>();
auto out_ptr = output.data_ptr<float>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0.0f, x_ptr[i]); // ReLU: max(0, x)
}
} else if (input.scalar_type() == torch::kFloat64) {
auto x_ptr = input.data_ptr<double>();
auto out_ptr = output.data_ptr<double>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0.0, x_ptr[i]);
}
} else if (input.scalar_type() == torch::kInt32) {
auto x_ptr = input.data_ptr<int32_t>();
auto out_ptr = output.data_ptr<int32_t>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0, x_ptr[i]);
}
} else if (input.scalar_type() == torch::kInt64) {
auto x_ptr = input.data_ptr<int64_t>();
auto out_ptr = output.data_ptr<int64_t>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0L, x_ptr[i]);
}
}
// 5. 转换回原类型
if (need_convert) {
output = output.to(dtype);
}
return output;
}
重要: 生成的代码必须遵循 KernelBench 格式规范,使用 Python 模块内嵌 C++ 代码 的方式。
下方模板可作为 CPU KernelBench 算子的起始实现。
import torch
from torch.utils.cpp_extension import load_inline
# 内联C++扩展代码
cpp_source = """
#include <torch/extension.h>
torch::Tensor op_name_kernel(torch::Tensor x) {
// 1. 确保输入张量是连续的
if (!x.is_contiguous()) {
x = x.contiguous();
}
// 2. 检查数据类型,支持多种类型
torch::ScalarType dtype = x.scalar_type();
bool need_convert = (dtype != torch::kFloat32 && dtype != torch::kFloat64 &&
dtype != torch::kInt32 && dtype != torch::kInt64);
torch::Tensor input = need_convert ? x.to(torch::kFloat32) : x;
// 3. 创建输出张量
torch::Tensor output = torch::zeros_like(input);
// 4. 根据数据类型分发计算
if (input.scalar_type() == torch::kFloat32) {
auto x_ptr = input.data_ptr<float>();
auto out_ptr = output.data_ptr<float>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
// 具体的算子计算逻辑
out_ptr[i] = compute_logic(x_ptr[i]);
}
} else if (input.scalar_type() == torch::kFloat64) {
// 同样的逻辑,但使用 double 类型
auto x_ptr = input.data_ptr<double>();
auto out_ptr = output.data_ptr<double>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = compute_logic(x_ptr[i]);
}
} else if (input.scalar_type() == torch::kInt32) {
auto x_ptr = input.data_ptr<int32_t>();
auto out_ptr = output.data_ptr<int32_t>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = compute_logic(x_ptr[i]);
}
} else if (input.scalar_type() == torch::kInt64) {
auto x_ptr = input.data_ptr<int64_t>();
auto out_ptr = output.data_ptr<int64_t>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = compute_logic(x_ptr[i]);
}
}
// 5. 转换回原类型
if (need_convert) {
output = output.to(dtype);
}
return output;
}
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("op_name_kernel", &op_name_kernel, "CPU op_name operator");
}
"""
# 动态加载C++扩展
op_name_module = load_inline(
name="custom_op_name",
cpp_sources=cpp_source,
extra_cflags=["-O3"],
verbose=True
)
# Python接口函数
def op_name(x: torch.Tensor) -> torch.Tensor:
if x.device.type != "cpu":
x = x.cpu()
return op_name_module.op_name_kernel(x)
load_inline 动态编译并加载扩展PYBIND11_MODULE 宏注册算子适用于激活函数、逐元素运算等简单操作。
// ReLU: max(0, x)
torch::Tensor relu_kernel(torch::Tensor x) {
if (!x.is_contiguous()) x = x.contiguous();
torch::ScalarType dtype = x.scalar_type();
bool need_convert = (dtype != torch::kFloat32 && dtype != torch::kFloat64);
torch::Tensor input = need_convert ? x.to(torch::kFloat32) : x;
torch::Tensor output = torch::zeros_like(input);
if (input.scalar_type() == torch::kFloat32) {
auto x_ptr = input.data_ptr<float>();
auto out_ptr = output.data_ptr<float>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0.0f, x_ptr[i]);
}
} else if (input.scalar_type() == torch::kFloat64) {
auto x_ptr = input.data_ptr<double>();
auto out_ptr = output.data_ptr<double>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0.0, x_ptr[i]);
}
}
if (need_convert) output = output.to(dtype);
return output;
}
适用于求和、最大值、最小值等聚合操作。
// Sum reduction: 沿指定维度求和
torch::Tensor sum_reduction_kernel(torch::Tensor x) {
if (!x.is_contiguous()) x = x.contiguous();
torch::ScalarType dtype = x.scalar_type();
bool need_convert = (dtype != torch::kFloat32 && dtype != torch::kFloat64);
torch::Tensor input = need_convert ? x.to(torch::kFloat32) : x;
int64_t numel = input.numel();
torch::Tensor output;
if (input.scalar_type() == torch::kFloat32) {
auto x_ptr = input.data_ptr<float>();
float result = 0.0f;
for (int64_t i = 0; i < numel; ++i) {
result += x_ptr[i]; // 求和归约
}
output = torch::tensor({result}, torch::kFloat32);
} else if (input.scalar_type() == torch::kFloat64) {
auto x_ptr = input.data_ptr<double>();
double result = 0.0;
for (int64_t i = 0; i < numel; ++i) {
result += x_ptr[i];
}
output = torch::tensor({result}, torch::kFloat64);
}
if (need_convert) output = output.to(dtype);
return output;
}
确保所有操作都有适当的边界检查和错误处理。
torch::Tensor safe_operation_kernel(torch::Tensor x) {
// 1. 检查张量有效性
TORCH_CHECK(x.numel() > 0, "Input tensor cannot be empty");
TORCH_CHECK(x.dim() > 0, "Input tensor must have at least one dimension");
// 2. 确保张量连续性
if (!x.is_contiguous()) {
x = x.contiguous();
}
// 3. 类型检查和转换
torch::ScalarType dtype = x.scalar_type();
bool need_convert = (dtype != torch::kFloat32 && dtype != torch::kFloat64);
torch::Tensor input = need_convert ? x.to(torch::kFloat32) : x;
torch::Tensor output = torch::zeros_like(input);
// 4. 安全的数据处理
if (input.scalar_type() == torch::kFloat32) {
auto x_ptr = input.data_ptr<float>();
auto out_ptr = output.data_ptr<float>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0.0f, x_ptr[i]);
}
} else if (input.scalar_type() == torch::kFloat64) {
auto x_ptr = input.data_ptr<double>();
auto out_ptr = output.data_ptr<double>();
int64_t numel = input.numel();
for (int64_t i = 0; i < numel; ++i) {
out_ptr[i] = std::max(0.0, x_ptr[i]);
}
}
if (need_convert) output = output.to(dtype);
return output;
}
// 类型检查
torch::ScalarType dtype = x.scalar_type();
bool is_float32 = (dtype == torch::kFloat32);
bool is_float64 = (dtype == torch::kFloat64);
bool is_int32 = (dtype == torch::kInt32);
bool is_int64 = (dtype == torch::kInt64);
// 类型转换
torch::Tensor input = x.to(torch::kFloat32); // 转换为 float32
torch::Tensor output = result.to(dtype); // 转换回原类型
if (!x.is_contiguous()) {
x = x.contiguous();
}
// float32 指针
auto x_ptr = input.data_ptr<float>();
auto out_ptr = output.data_ptr<float>();
// float64 指针
auto x_ptr = input.data_ptr<double>();
auto out_ptr = output.data_ptr<double>();
// int32 指针
auto x_ptr = input.data_ptr<int32_t>();
auto out_ptr = output.data_ptr<int32_t>();
// int64 指针
auto x_ptr = input.data_ptr<int64_t>();
auto out_ptr = output.data_ptr<int64_t>();
// 创建输出张量
torch::Tensor output = torch::zeros_like(input); // 同形状零张量
torch::Tensor output = torch::ones_like(input); // 同形状单位张量
torch::Tensor output = input.clone(); // 克隆张量
// 张量属性
int64_t numel = input.numel(); // 元素总数
int64_t dim = input.dim(); // 维度数
torch::IntArrayRef shape = input.sizes(); // 形状
TORCH_CHECK(x.numel() > 0, "Input tensor cannot be empty");
TORCH_CHECK(x.dim() > 0, "Input tensor must have at least one dimension");
omp_get_thread_num()等OpenMP运行时API// ❌ 错误:在受限上下文中调用OpenMP API
std::mt19937 gen(seed + omp_get_thread_num()); // 编译错误!
// ✅ 正确:在并行区域内正常调用
#pragma omp parallel
{
int tid = omp_get_thread_num(); // 正确
std::mt19937 gen(seed + tid);
}
本文件的模板、API 注意事项和优化建议已经覆盖 CPU KernelBench 算子的常用实现路径。