[2026春季][T2-2-1]ChaoticLuna - #188
Conversation
chen2021673
left a comment
There was a problem hiding this comment.
在修改逻辑细节前建议先完成以下整体整理:
- 收敛 PR 范围。 删除 benchmark 、Tokenizer、MNIST、Tensor::To、Exp backward 等无关修改(如觉得必要可以单独PR修复);
- 清理个人开发环境内容例如 .gitignore 文件;
- 不要引入第二套 distribution_stubs 体系。 仓库已有 dispatcher,应优先复用现有机制;
- 现在创建 CPU/CUDA Generator 必须包含 src/..._generator_impl.h,建议提供公共的 CreateGenerator(Device, seed) 等接口,隐藏具体 Impl;
- 统一注释与 include 规范。 新增 C++ 注释统一改成简洁英文,删除“比赛要求”“仿 PyTorch XX 行”及“//用struct能记录”等开发期说明。做一次 header self-contained/IWYU 检查及格式检查;
- 如果声明支持 FP16/BF16/FP32/FP64,请补充测试。
- 整理提交历史,自行 Review 代码,确认逻辑清晰简洁,尽量达到可合入标准。
4eda57f to
41cb406
Compare
|
|
||
| } // namespace | ||
|
|
||
| void Uniform(const std::shared_ptr<Tensor> &tensor, double from, double to, const std::optional<Generator> &gen) { |
There was a problem hiding this comment.
这里注册的函数参数为 const std::optional<Generator>& generator),但现有 Dispatcher 的调用逻辑中,ArgsT... 按值推导,调用的应该是 std::optional<Generator>,这两个函数指针类型不相同。直接修改这里的类型即可。
There was a problem hiding this comment.
已按现有 Dispatcher 的按值调用约束,将本 PR 中注册的随机 kernel 的 std::optional 统一改为按值传递,见 383657e。
不过同时注意到 KernelFunction::Call 已有“支持自动推导返回值和参数类型”的 TODO。当前的类型擦除调用无法保留注册函数的精确引用类型,仓库既有部分 kernel 的引用参数也有同样的限制如ScatterForward、GatherForward;根治需要调整 Dispatcher 的注册与调用机制,超出本 PR 范围,因此本次未改动既有 kernel。感谢指出。
|
赛题报告如有和代码不符的地方请尽快更新。 |
3ea06c8 to
383657e
Compare
|
已更新文档 |
| @@ -0,0 +1,130 @@ | |||
| #pragma once | |||
There was a problem hiding this comment.
这个头文件是公开的,建议区分 generator.h 和 generator_impl.h 文件,避免把 GeneratorImpl 暴露给外部。
| // Prefer check_generator<T>(); this unchecked accessor assumes a matching backend. | ||
| template <typename T> T *get() const { return static_cast<T *>(impl_.get()); } | ||
|
|
||
| GeneratorImpl *unsafeGetGeneratorImpl() const { return impl_.get(); } |
There was a problem hiding this comment.
get()和unsafeGetGeneratorImpl() 等一系列接口作为 public API 不合理,它相当于为了实现内部 check_generator(),把整个封装打穿了。建议删除这里的不安全接口
get<T>()
unsafeGetGeneratorImpl()
make_generator()
check_generator()
get_generator_or_default()
detail::check_rng_state()
其中公开的 get() 和 unsafeGetGeneratorImpl() 可以删除,其他类型检查和默认 Generator 解析移动到 generator_impl.h,通过私有 friend accessor 获取实现
class GeneratorImpl {
private:
friend class GeneratorAccessor;
};
class GeneratorAccessor {
public:
static GeneratorImpl &Get(const Generator &generator) {
if (!generator.impl_) {
throw std::invalid_argument("Undefined Generator");
}
return *generator.impl_;
}
static std::mutex &Mutex(const Generator &generator) {
return Get(generator).mutex_;
}
};
template <typename T>
T &CheckedGeneratorImpl(const Generator &generator,
const Device &expected_device) {
static_assert(std::is_base_of_v<GeneratorImpl, T>);
auto &base = GeneratorAccessor::Get(generator);
if (base.device() != expected_device) {
throw std::invalid_argument("Generator device mismatch");
}
auto *typed = dynamic_cast<T *>(&base);
if (typed == nullptr) {
throw std::invalid_argument("Generator backend mismatch");
}
return *typed;
}
template <class Impl, class... Args>
Generator MakeGenerator(Args &&...args);
void CheckRngState(const Tensor &state);类似这样。注意命名统一遵循 Google 风格。
There was a problem hiding this comment.
这里 MakeGenerator() 需要构造私有 Generator,也可以让 GeneratorAccessor 提供内部构造函数。
| #include <memory> | ||
| #include <optional> | ||
| #include <random> | ||
|
|
| #include "infini_train/include/datatype.h" | ||
| #include "infini_train/include/device.h" | ||
| #include "infini_train/include/dispatcher.h" | ||
| #include "infini_train/include/tensor.h" |
There was a problem hiding this comment.
tensor.h 中的 <random> 删除后,这里可能因为缺头文件编译失败,加一下。
| if (!training || p == 0.0 || input->NumElements() == 0) { | ||
| return input; | ||
| } | ||
| return std::make_shared<autograd::Dropout>(p, std::move(generator))->Apply({input})[0]; |
There was a problem hiding this comment.
用了std::move,根据IWYU,缺<utility>头文件
|
|
||
| template <typename random_t> __device__ random_t uniform_sample(curandStatePhilox4_32_10_t *state) { | ||
| if constexpr (std::is_same_v<random_t, double>) { | ||
| return 1.0 - curand_uniform_double(state); |
|
|
||
| namespace { | ||
|
|
||
| std::shared_ptr<Tensor> CopyToCPU(const std::shared_ptr<Tensor> &tensor) { |
There was a problem hiding this comment.
这个函数不需要吧,用自带的 Tensor->To() 即可
| return host; | ||
| } | ||
|
|
||
| std::vector<uint8_t> TensorBytes(const std::shared_ptr<Tensor> &tensor) { |
| } | ||
| core::DeviceGuard guard(device); | ||
| auto *cuda_generator = get_generator_or_default<core::cuda::CUDAGeneratorImpl>( | ||
| gen, core::cuda::getDefaultCUDAGenerator(device.index())); |
There was a problem hiding this comment.
这里只通过 get_generator_or_default 内部检查了 backend 类型,没有检查 CUDA index。因此 cuda:0 Generator 可以为 cuda:1 tensor 生成数据,不安全。
| std::vector<int64_t>{static_cast<int64_t>(valid_state->SizeInBytes() - 1)}, DataType::kUINT8, Device()); | ||
| EXPECT_DEATH(generator.set_state(*truncated), "Check failed"); | ||
|
|
||
| if (device.IsCUDA()) { |
There was a problem hiding this comment.
不应在通用测试里使用 device.IsCUDA()、 device.IsCPU() 选择行为。当前测试已经通过参数化 fixture 和 CTest 的 cpu/cuda label 区分 backend。建议:
- 通用测试只使用 GetDevice(),不包含 backend 选择分支。
- CPU 特有语义拆到 CPU-only 测试,CUDA 特有语义拆到 CUDA-only 测试。可参考 tests/tensor/CMakeLists.txt 的 shared、cpu_only、cuda_only 结构。
|
整体设计思路清晰、完成度较高。希望能够进一步修改,后续继续共同推动合入,将工作成果体现在开源框架里~ |



赛题报告.pdf
HONOR_CODE.md
REFERENCE.md
2026 春季人工智能大赛赛题报告
一、设计与实现
下文按照赛题《【2026 春季人工智能大赛】Generator 抽象选题》的任务拆解,依次说明 Generator 抽象与状态管理、CPU/CUDA 后端实现、默认 Generator 与统一随机种子,以及随机算子的接入方式。每一部分同时说明与 PyTorch 的语义对应和当前实现边界。
下图概览 Generator 句柄如何经由 CPU/CUDA 后端向随机 kernel 提供状态,并由 Dispatcher 按设备完成分发。
1. Generator 抽象与状态管理
1.1 接口
对外暴露的接口集中在
infini_train/include/generator.h。底层抽象为GeneratorImpl基类,其中 seed/state 是纯虚接口,device()和clone()由基类提供通用实现。Generator(类)infini_train/include/generator.hinfini_train/src/generator.ccat::Generator,底层为c10::GeneratorImplGeneratorImpl;clone()用于深拷贝。句柄与 clone 语义基本对齐,智能指针分别为std::shared_ptr与c10::intrusive_ptr。Generator::set_current_seed()/Generator::current_seed()GeneratorImpl纯虚接口,infini_train/include/generator.hCPU:
infini_train/src/core/runtime/cpu/cpu_generator_impl.ccCUDA:
infini_train/src/core/runtime/cuda/cuda_generator_impl.ccat::Generator::set_current_seed()/at::Generator::current_seed()Generator::seed()GeneratorImpl纯虚接口,infini_train/include/generator.hCPU:
infini_train/src/core/runtime/cpu/cpu_generator_impl.ccCUDA:
infini_train/src/core/runtime/cuda/cuda_generator_impl.ccat::Generator::seed()Generator::get_state()/Generator::set_state()GeneratorImpl纯虚接口,infini_train/include/generator.hCPU:
infini_train/src/core/runtime/cpu/cpu_generator_impl.ccCUDA:
infini_train/src/core/runtime/cuda/cuda_generator_impl.ccat::Generator::get_state()/at::Generator::set_state()Generator::device()infini_train/include/generator.h头文件内联实现
at::Generator::device()Generator::clone()infini_train/include/generator.h基类
GeneratorImpl::clone()在头文件内联实现;后端通过clone_impl()实现深拷贝at::Generator::clone()Generator::mutex()infini_train/include/generator.h头文件内联实现
at::Generator::mutex()infini_train::CreateGenerator()infini_train/include/generator.hinfini_train/src/generator.ccat::make_generator<Impl>(),后端的createCPUGenerator()/createCUDAGenerator()infini_train::GetDefaultGenerator()(见下文)infini_train/include/generator.hinfini_train/src/generator.ccat::globalContext().defaultGenerator(Device)infini_train::manual_seed()(见下文)infini_train/include/generator.hinfini_train/src/generator.cctorch.manual_seed()1.2 设计说明
Generator是上层可持有的轻量句柄,只保存一个std::shared_ptr<GeneratorImpl>。因此复制Generator不会复制随机状态,两个句柄会继续消费同一条随机流;调用clone()才会得到状态独立、初始内容相同的 Generator。这个语义把“共享同一随机流”和“复制出一条新随机流”区分为两个显式操作。GeneratorImpl负责定义不同设备 Generator 共有的状态接口,CPU 和 CUDA 分别提供派生实现。随机算子只接收Generator,不直接依赖某个后端的实现类型。后端类和相关头文件放在src/core/runtime/下,普通调用路径无需接触std::mt19937、Philox 或 curand 等随机引擎细节。创建 Generator 时,
CreateGenerator根据Device选择相应后端实现,调用方不需要包含后端 Impl 头文件。后续接入新的设备类型时,可以增加对应的GeneratorImpl派生类和创建分支,而无需改变上层随机算子的 Generator 参数形式。实现中将 seed 与 state 分开处理。
set_current_seed()用于重新初始化随机流,get_state()与set_state()用于保存和恢复已经推进到的位置;随机算子每次使用 Generator 后都会推进其状态。state 的具体编码由后端自行维护,因此公共接口只传递状态对象,不依赖某一种随机引擎的内部表示。互斥锁归属于
GeneratorImpl。Uniform、Normal 和 Dropout 的 kernel 在消费同一 Generator 时持锁,避免并发调用同时推进同一份状态;如果调用方需要将多个 Generator 操作作为一个原子过程执行,则需要通过Generator::mutex()自行界定加锁范围。1.3 对齐与差异
以下比较基于 2026-08-01 拉取的 PyTorch main(
85728e11a5a98c344c4596880855e35046db81b0)中的ATen/core/Generator.h、c10/core/GeneratorImpl.h及 CPU/CUDA Generator 实现。基本一致的行为:两边都采用“用户侧 Generator 句柄 + 设备相关 GeneratorImpl”的多态结构,普通句柄复制共享同一 Impl,
clone()才创建独立状态,Impl 的 Copy/Move 均被删除。set_current_seed()、current_seed()、seed()、get_state()、set_state()和device()的核心用途相同;默认 Generator 都按设备维护并延迟创建。公开的 state 载体也都是 CPU 字节 Tensor,而不是裸字节数组。未对齐的行为:InfiniTrain 用
std::shared_ptr,PyTorch 用c10::intrusive_ptr,因此没有unsafeReleaseGeneratorImpl()、getIntrusivePtr()等所有权和运行时集成接口。两边的 state 二进制布局不同:本实现使用后端 magic、CPU engine 序列化或 CUDA subsequence,PyTorch CPU 使用固定大小 POD,CUDA 使用 seed 与 Philox offset;本实现没有显式 version 字段,公共检查也未验证 state 连续性。线程语义也不完全一致,PyTorch 要求调用方为非只读 Generator 操作持有 mutex,而本实现仅对已接入的 Uniform、Normal、Dropout kernel 自动加锁,直接变更状态或组合多个操作仍由调用方协调。此外,PyTorch 提供set_offset()、get_offset()、philox_state()和 CUDA Graph 的 graph-safe state 接口;本实现通过内部philox_subsequence()满足普通 CUDA kernel 的区间预留需求,这些超出赛题范围的扩展能力未纳入当前实现。2. CPU 与 CUDA 后端 Generator
2.1 接口
CPU 和 CUDA 后端都继承
GeneratorImpl,对外统一实现 seed/state/device/clone 接口。为了服务上层 kernel,两个后端还暴露了一些后端专用方法,这些方法只在src/内部使用。CPUGeneratorImpl(类)infini_train/src/core/runtime/cpu/cpu_generator_impl.hinfini_train/src/core/runtime/cpu/cpu_generator_impl.ccat::CPUGeneratorImplstd::mt19937。后端角色与 seed/state 语义对齐,具体 engine 类型不同。CUDAGeneratorImpl(类)infini_train/src/core/runtime/cuda/cuda_generator_impl.hinfini_train/src/core/runtime/cuda/cuda_generator_impl.ccat::cuda::CUDAGeneratorImplCPUGeneratorImpl::get_state()/CPUGeneratorImpl::set_state()infini_train/src/core/runtime/cpu/cpu_generator_impl.hinfini_train/src/core/runtime/cpu/cpu_generator_impl.ccat::CPUGeneratorImpl::get_state()/set_state()CUDAGeneratorImpl::get_state()/CUDAGeneratorImpl::set_state()infini_train/src/core/runtime/cuda/cuda_generator_impl.hinfini_train/src/core/runtime/cuda/cuda_generator_impl.ccat::cuda::CUDAGeneratorImpl::get_state()/set_state()CPUGeneratorImpl::random()/CPUGeneratorImpl::random64()infini_train/src/core/runtime/cpu/cpu_generator_impl.hinfini_train/src/core/runtime/cpu/cpu_generator_impl.ccat::CPUGeneratorImpl::random()/random64()CPUGeneratorImpl::next_float_normal_sample()/set_next_float_normal_sample()next_double_normal_sample()/set_next_double_normal_sample()infini_train/src/core/runtime/cpu/cpu_generator_impl.hinfini_train/src/core/runtime/cpu/cpu_generator_impl.ccat::CPUGeneratorImpl的同名 float/double 缓存接口CUDAGeneratorImpl::philox_subsequence()infini_train/src/core/runtime/cuda/cuda_generator_impl.hinfini_train/src/core/runtime/cuda/cuda_generator_impl.ccat::cuda::CUDAGeneratorImpl::philox_cuda_state(increment)上层 kernel 不直接引用
CPUGeneratorImpl或CUDAGeneratorImpl,而是通过check_generator<T>()和get_generator_or_default<T>()在内部转换。2.2 设计说明
CPU 后端使用
std::mt19937。构造时将 64 位 seed 的高、低 32 位同时交给std::seed_seq初始化 engine,避免直接调用std::mt19937(seed)时高 32 位被截断。CPU 的 Uniform 和 Normal 通过distributions_helper.h消费 engine;Normal 采用 Box-Muller,并把尚未消费的第二个样本缓存到 Generator 中。因此,CPU state 除 engine 以外,还需要保存 seed 和 float/double 两种缓存。CUDA 后端不保存每个元素的
curandState,而是保存 seed 和下一段可分配的 Philox subsequence。一次随机 kernel 启动前,在锁保护下调用philox_subsequence(n)预留区间;kernel 随后以curand_init(seed, subsequence + index, 0, &state)为各元素构造独立状态。这样后续调用从新的 subsequence 开始,不会与已经启动的 kernel 重用随机区间。两个后端都将 state 作为 CPU
UINT8Tensor 返回。set_state()先检查该公共载体,再由后端检查长度和 magic,因此 CPU/CUDA state 会相互拒绝,长度、dtype、设备或 magic 不符合要求的 state 也会失败。CPU 还会检查 engine 序列化内容和缓存标志;CUDA 的固定字段格式不对 seed 与 subsequence 的数值额外作完整性校验。当前 state 使用 backend magic 区分来源,但没有显式 version 字段;CUDA state 也不编码 device index,因此同一 CUDA backend 的 state 可以恢复到另一张 CUDA 卡。state 格式属于后端私有实现,不保证跨版本兼容。2.3 对齐与差异
基本一致的行为:CPU 使用 Mersenne Twister、CUDA 使用 Philox;CUDA 默认 Generator 按设备维度独立维护。两边都不要求 CPU 与 CUDA 在相同 seed 下生成逐元素一致的结果。
未对齐的行为:PyTorch CPU state 是固定大小的 POD 结构,本实现将 engine 序列化为字符串,因此大小可变。PyTorch CUDA 的常规 state 使用 seed 与 Philox offset,本实现使用带 magic 的 seed 与 subsequence。PyTorch 还提供公开的 offset 控制和 CUDA Graph 相关接口;本实现通过内部
philox_subsequence()满足普通 CUDA kernel 的区间预留需求,未覆盖这些超出赛题范围的扩展能力。3. 默认 Generator 与全局随机种子
3.1 接口
infini_train::GetDefaultGenerator(Device)infini_train/include/generator.hinfini_train/src/generator.ccat::globalContext().defaultGenerator(Device)infini_train::manual_seed()infini_train/include/generator.hinfini_train/src/generator.cctorch.manual_seed()3.2 设计说明
默认 Generator 是框架持有的随机状态来源。CPU 维护一个进程级单例;CUDA 按设备索引维护默认 Generator,首次请求该设备时才创建。
GetDefaultGenerator(Device)根据设备类型与 CUDA 设备索引分派并返回对应句柄,因此重复获取同一设备会共享同一份随机状态,不同 CUDA 设备的默认状态彼此独立。随机算子的 Generator 参数为可选项。调用方传入已定义的
Generator时,算子直接使用该句柄,不会消耗默认 Generator;未传入参数或传入未定义的Generator{}时,算子根据目标 Tensor 所在设备取得默认 Generator。显式 Generator 仍会校验后端类型,CPU Generator 不能用于 CUDA kernel,反之亦然。manual_seed(uint64_t)是统一的显式设种子入口。它先重置 CPU 默认 Generator,再初始化并逐个重置所有可见 CUDA 设备的默认 Generator。重置过程在各自的 mutex 保护下进行。该函数只影响默认 Generator,不会改变调用方通过CreateGenerator()创建的独立 Generator;在相同种子、设备与随机算子调用顺序下,默认路径可稳定复现。3.3 对齐与差异
基本一致的行为:PyTorch 通过
at::globalContext().defaultGenerator(Device)获取设备默认 Generator,CPU 与 CUDA 后端再分别维护对应实例。本实现的GetDefaultGenerator(Device)采用相同的按设备获取语义。两边的manual_seed都会重置 CPU 默认 Generator 与当前可见 CUDA 设备的默认 Generator,显式传入的 Generator 也都会优先于默认路径使用。未对齐的行为:PyTorch 的 Context 可以通过 accelerator hooks 路由到更多设备后端,本实现当前只覆盖 CPU 与 CUDA。PyTorch 的默认 Generator 获取主要位于 Context 与后端内部接口中,本实现将
GetDefaultGenerator(Device)作为直接的公共入口。全局设种子只覆盖框架默认状态,不会替显式创建的 Generator 改种子,这一边界与 PyTorch 一致;若后续接入新的设备后端,需要补充对应的默认 Generator 管理与manual_seed路径。4. 随机算子接入
4.1 接口
infini_train::nn::init::Uniform()infini_train/include/nn/init.hinfini_train/src/nn/init.cctorch.nn.init.uniform_()infini_train::nn::init::Normal()infini_train/include/nn/init.hinfini_train/src/nn/init.cctorch.nn.init.normal_()infini_train::nn::init::KaimingUniform()infini_train/include/nn/init.hinfini_train/src/nn/init.cctorch.nn.init.kaiming_uniform_()Tensor::Uniform()。计算 fan、gain 和边界的目标语义对齐。Tensor::Uniform()infini_train/include/tensor.hinfini_train/src/tensor.ccTensor.uniform_()nn::init::Uniform()。原地均匀填充语义对齐。infini_train::nn::function::Rand()infini_train/include/nn/functional.hinfini_train/src/nn/functional.cctorch.rand()infini_train::nn::function::Randn()infini_train/include/nn/functional.hinfini_train/src/nn/functional.cctorch.randn()infini_train::nn::function::Dropout()infini_train/include/nn/functional.hinfini_train/src/nn/functional.cctorch.nn.functional.dropout()上述接口均以
std::optional<Generator>接收可选 Generator。未传入参数或传入未定义的Generator{}时,后端回退到目标 Tensor 设备的默认 Generator。4.2 设计说明
初始化与训练期随机算子共用同一条 Generator 接入路径。
Rand与Randn创建目标 Tensor 后,分别转发到Uniform与Normal;KaimingUniform先根据 fan 和 gain 计算边界,再调用Tensor::Uniform。这些上层接口只传递可选 Generator,并通过Dispatcher::Instance().Call进入按设备注册的 CPU 或 CUDA kernel,不直接依赖std::mt19937、curand 或 Philox 的具体类型。后端 kernel 通过
get_generator_or_default()解析可选参数。CPU kernel 取得 Generator 后持锁,逐样本消费std::mt19937engine;CUDA kernel 在持锁范围内读取 seed 并按 Tensor 元素数预留 Philox subsequence,随后在 kernel 中以curand_init(seed, subsequence + index, 0, &state)初始化每个元素的随机状态。一次实际抽样会推进所选 Generator 的状态,因而相同 seed、设备、Tensor 形状和调用顺序能够复现同一后端上的结果。并发调用虽受 mutex 保护,但锁竞争顺序本身不构成可复现的调用顺序。Dropout将可选 Generator 保存在autograd::Dropout中,并交给DropoutForwardkernel 生成输出与UINT8mask。mask 被标记为不可微并保存到上下文,反向阶段由DropoutBackward依照同一 mask 缩放梯度,不再消耗随机状态。training=false、p=0、p=1或空 Tensor 不进行实际抽样。CPU/CUDA 的 distribution 和 Dropout kernel 均覆盖FLOAT16、BFLOAT16、FLOAT32、FLOAT64四种浮点 dtype。4.3 对齐与差异
基本一致的行为:
Uniform、Normal、KaimingUniform、Rand与Randn都可选择显式 Generator 或设备默认 Generator,语义对应 PyTorch 初始化函数及torch.rand、torch.randn的 generator 参数。两边的 Dropout 都在前向阶段生成并保存 mask,反向阶段复用该 mask;CPU 与 CUDA 的随机算法不同,因此只承诺各后端在相同调用条件下可复现,不承诺跨设备逐元素一致。未对齐的行为:本实现将
std::optional<Generator>直接暴露给Dropout,方便训练代码显式控制随机流;PyTorch 的torch.nn.functional.dropout公共接口没有 generator 参数,通常使用当前设备默认 Generator。本实现的 Dropout 没有 inplace 选项,随机初始化覆盖范围也只包含本题接入的 Uniform、Normal 和 KaimingUniform,未扩展到 PyTorch 的全部随机算子与初始化策略。后续新增随机算子时,可沿用可选 Generator 参数、后端校验和 kernel 内状态预留这条接入路径。二、其他改动与后续工作
DDP 构造阶段参考 PyTorch 的初始化同步语义,由 rank 0 将模块参数和 buffer 原地广播到其余 rank,使各卡在训练开始前持有一致的模型状态。目前的实现不试图改变单进程多线程训练时共享 CPU 默认 Generator 的语义。多个 rank 对默认随机流的消费顺序受线程调度影响,因此即使重复相同操作,也不保证跨次运行得到完全相同的随机序列。后续可考虑两条路线:采用类似
torchrun的一 GPU 一进程启动方式,使各 rank 拥有独立进程内 RNG;或参考 Megatron 的思路,为不同线程提供隔离的局部随机流。后者会扩展全局默认 Generator 的设计边界,因此未纳入本题实现范围。三、验证与复现
3.1 验证环境
本节正式结果来自租用的 7 卡 CUDA 服务器,运行日志见后文图片。配置如下。
/usr/bin/g++-13CMAKE_CUDA_ARCHITECTURES=89USE_CUDA=ON,USE_NCCL=ON,BUILD_TEST=ON3.2 测试内容与结果
Generator 测试位于
tests/generator/。test_generator_cpu与test_generator_cuda由同一套参数化 gtest 源码生成;本次分别通过--gtest_filter='CPU/*'和--gtest_filter='CUDA/*'选择对应参数实例。因此两行覆盖的用例互不重复,可以合并阅读。test_generator_cputest_generator_cudatest_generator_ddp两组 Generator 测试共 34 条通过、4 条按后端条件跳过,没有失败用例。CPU 筛选跳过 CUDA 专用项,CUDA 筛选跳过 CPU 专用项;由于服务器有 7 张 GPU,所有需要至少 2 张 GPU 的用例均实际运行。
核心测试覆盖了本题的四类功能。
test_generator_core.cc验证 Generator 的句柄和 state 语义、默认 Generator 与显式 Generator 的选择、CPU/CUDA 后端不匹配时的拒绝,以及初始化入口的可复现性;test_generator_random_ops.cc验证Rand、Randn、Dropout的固定随机脚本重放、默认状态不受显式 Generator 消耗、四种浮点 dtype、非连续 view 的写入范围、Dropout mask 与反向计算,以及非法参数的失败路径。DDP 用例是附带验证,关注多 GPU 环境中模块参数的初始同步,不改变 Generator 的公共语义。在仓库根目录配置并构建测试:
进入构建目录后运行 Generator 测试。若运行环境未为 glog 或 CUDA 配置动态库搜索路径,可先设置
LD_LIBRARY_PATH。CPU 筛选会跳过 CUDA 专用用例,CUDA 筛选会跳过 CPU 专用用例。若机器少于两张 GPU,CUDA 的跨卡 Generator、各设备默认 Generator 独立性和 DDP 测试还会按条件跳过。多卡服务器若无法由 CMake 自动探测架构,可在配置命令中额外传入
-DCMAKE_CUDA_ARCHITECTURES=89,用于 RTX 4090 D。2026 春季启元人工智能大赛诚信守则(Honor Code)
本人作为 2026 春季启元人工智能大赛(以下简称“比赛”)的参赛选手,郑重承诺严格遵守比赛规则及本诚信守则,秉持诚信、公正、廉洁的参赛原则,自觉维护比赛的公平性与严肃性。本人充分理解并认可,违反本准则将导致参赛资格被取消、比赛成绩作废等相应后果,且愿意承担由此产生的一切责任。
一、参赛诚信承诺
本人保证所提交的赛题PR(Pull Request)中包含的算子实现代码及相关文档,均为本人(及参赛团队,如为团队参赛)在比赛期间独立完成或在明确标注参考来源的基础上进行开发,不存在任何欺诈、抄袭、作弊行为。
本人承诺主动、全面、真实地披露赛题实现过程中所有参考的外部资源,尤其是开源代码资源,不隐瞒任何可能影响比赛公平性的信息。
本人保证不采用任何不正当手段获取比赛优势,包括但不限于窃取其他参赛选手的代码成果、利用非比赛允许的工具或技术、与他人串通作弊等。
二、参考资源说明
本人确认已按比赛要求,将本次赛题实现过程中涉及的参考资源信息单独撰写至
REFERENCE.md文件中,该文件将与本诚信守则一同作为PR附件提交。REFERENCE.md需根据实际参考情况,按以下要求完整填写,信息不完整或虚假填写将视为违反本准则:情况1:无参考外部开源代码及核心实现思路
REFERENCE.md中需明确声明:“本次赛题提交的算子代码、核心算法逻辑及实现方案均为本人(及参赛团队)独立设计与开发,未参考任何外部开源项目、技术文档中的核心代码片段或实现思路,未接受任何第三方的技术指导或代码支持。”情况2:有参考外部开源代码及相关资源
对每个参考资源提供以下信息陈述:
参考开源项目/资源名称
参考资源链接(GitHub/Gitee/论文/技术文档等)
参考的具体内容(请明确说明参考的代码片段、算法逻辑、实现思路等,需标注对应资源的具体位置,如文件路径、代码行数等)
本人对参考内容的修改与优化说明:(请详细说明在参考基础上,本人所做的独立开发、修改、优化工作,体现自身技术贡献)
若是开源项目,提供参考资源的开源协议类型:(如MIT、Apache 2.0、GPL等)
其他需要补充说明的信息
三、禁止行为确认
本人明确知晓并承诺避免以下违反比赛公平性的行为,若存在以下任一情况,自愿接受比赛组委会的相应处罚:
未经授权复制、抄袭他人(包括其他参赛选手、开源项目、商业代码)的代码、算法或技术方案,且未进行明确标注;
隐瞒或虚假披露参考资源信息,包括遗漏重要参考来源、伪造参考内容说明等;
与其他参赛选手或第三方串通,进行代码共享、成果交换等违规协作;
利用比赛平台漏洞、技术缺陷或非比赛允许的工具获取不正当利益;
伪造比赛相关证明材料、提交虚假信息;
其他违反比赛规则及公序良俗的不诚信行为。
四、责任与确认
本人充分理解,比赛组委会将对所有提交的PR进行代码溯源、参考信息核查等公平性审查,若发现本人存在违反本准则的行为,有权随时取消本人的参赛资格、作废比赛成绩,情节严重的将在比赛相关平台进行公示。
若因本人违反本准则导致比赛争议或第三方权益受损(如开源协议侵权等),本人将独立承担全部法律责任及相关损失,与比赛组委会无关。
本人确认已仔细阅读并完全理解本诚信守则的全部内容,自愿签署本准则,接受比赛组委会的监督与审查。
五、签署信息
参赛选手姓名(团队参赛需填写所有成员姓名)
李源,王柯翰,狄凡瑞
签署日期
2026年7月12日
REFERENCE
本项目在比赛提供的 InfiniTrain 代码库上完成。实现时参考了 PyTorch 对随机数状态、默认 Generator 和训练期随机算子的公开语义与实现思路;代码结合 InfiniTrain 现有的
Tensor、Device、Dispatcher、Autograd 和构建结构独立完成。PyTorch Generator、随机算子与 DDP
资源: PyTorch
主要参考:
本项目没有复制 PyTorch 的实现。CPU 后端使用
std::mt19937保存随机序列状态,CUDA 后端以 seed 和 Philox subsequence 管理 kernel 所需的随机区间;两者通过 InfiniTrain 的Dispatcher注册并分发 CPU/CUDA kernel。项目目标是保持 Generator 的使用和可复现语义,不要求 CPU 与 CUDA 在相同 seed 下产生逐位一致的随机数,也未覆盖 CUDA Graph 等扩展接口。AI 工具
资源名称:OpenAI Codex,Claude Code
资源链接:https://openai.com/codex
参考内容:用于协助整理实验记录、分析 benchmark 结果、撰写报告,并辅助生成小范围代码改动方案。
修改与优化:最终代码与实验决策均由参赛团队确认;
协议:不涉及开源代码复用。