资讯动态

Apache Arrow 中 vendored PCG 随机数生成器的引入、定制与工程实践

发布时间:2026/9/13 23:37:46 来源:尧图企业网站定制
Apache Arrow 中 vendored PCG 随机数生成器的引入、定制与工程实践【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrowApache Arrow 的 C 实现cpp/为了在数据分区、T‑PC‑H 数据生成、random计算内核等场景获得确定性、可复现、线程友好的伪随机数来源以源码内嵌vendored方式引入了 PCG 随机数生成库并做了命名空间隔离与平台适配。本文以 cpp/src/arrow/vendored/pcg/README.md 为主线说明该内嵌库的来源、改动清单以及它在 Arrow 计算与执行引擎中的真实用法帮助你理解 Arrow 内部随机数的设计取舍与引入路径。PCG 与 vendored 目录概览PCGPermuted Congruential Generator是 Melissa ONeill 提出的伪随机数生成方案相比经典的 LCG 具有更好的统计质量与更快的速度同时保留了 C11random兼容的接口。Arrow 没有把 PCG 作为外部依赖编译进来而是将其 C 头文件实现整体内嵌在仓库中目录结构如下cpp/src/arrow/vendored/pcg/ ├── CMakeLists.txt ├── README.md ├── pcg_extras.hpp ├── pcg_random.hpp └── pcg_uint128.hpppcg_random.hpp 是 PCG 引擎的主实现约 1954 行包含多种输出函数XSH RR、XSH RS、XSL RR、RXS M XS、XSL RR RR 等、多种流类型MCG、单流 LCG、可设流 LCG、唯一流 LCG以及一整套pcg32/pcg64等便利 typedefpcg_extras.hpp 提供 128 位整数支持、位旋转等底层工具与seed_seq_from种子序列辅助类pcg_uint128.hpp 用于在不原生支持 128 位整数的平台上模拟 128 位算术CMakeLists.txt 只有一行实质内容arrow_install_all_headers(arrow/vendored/pcg)即把该目录下的头文件统一安装到arrow/vendored/pcg路径下供 Arrow 内部源码#include arrow/vendored/pcg/pcg_random.hpp使用。整个内嵌库以 Apache-2.0 与 MIT 双许可发布SPDX-License-Identifier: (Apache-2.0 OR MIT)符合 Arrow 自身 Apache-2.0 许可的兼容要求。来源与改动清单README 的核心内容根据 README.mdArrow 内嵌的 PCG 源码取自 pcg-cpp 项目的 git changesetffd522e7188bef30a00c74dc7eb9de5faff90092在此基础上只做了三处改动命名空间隔离将整个库封闭进arrow_vendored命名空间。这样既保留了上游代码结构又避免了与用户项目或其他依赖库中可能存在的 PCG 符号发生 ODR 冲突移除struct arbitrary_seed定义原因是 Apache Arrow issue #35596。从当前仓库看pcg_random.hpp中已不存在该结构体Arrow 统一改用标准SeedSequence机制seed_seq_from来构造种子启用 MSVC ARM64 内建函数intrinsics允许在 Windows ARM64 上使用 Visual Studio 构建。对应改动来自 Apache Arrow PR #47779。这三处改动体现了 Arrow 内嵌第三方头文件库时的一贯策略保持源码完整、只做最小必要修改并把每次修改的原因记录在 README 中便于后续同步上游。命名空间隔离的落地方式arrow_vendored命名空间定义在 pcg_random.hpp 中所有引擎与辅助类都位于其下。Arrow 随后在 cpp/src/arrow/util/pcg_random.h 中用using别名把常用类型重新导出到arrow::random命名空间#include arrow/vendored/pcg/pcg_random.hpp // IWYU pragma: export namespace arrow { namespace random { using pcg32 ::arrow_vendored::pcg32; using pcg64 ::arrow_vendored::pcg64; using pcg32_fast ::arrow_vendored::pcg32_fast; using pcg64_fast ::arrow_vendored::pcg64_fast; using pcg32_oneseq ::arrow_vendored::pcg32_oneseq; using pcg64_oneseq ::arrow_vendored::pcg64_oneseq; } // namespace random } // namespace arrow因此 Arrow 内部源码无需感知 vendored 细节只需包含arrow/util/pcg_random.h即可使用arrow::random::pcg32_fast等类型这也是仓库中几乎所有使用点的统一入口。PCG 引擎族从 typedef 看可用性上游 pcg-cpp 在 pcg_random.hpp 中提供了一组面向不同场景的 typedefArrow 内嵌版本完整保留了这些定义typedef引擎状态位宽 → 输出位宽典型用途pcg32setseq XSH RR64→32可设流通用 32 位输出pcg32_oneseqoneseq XSH RR64→32单流确定性子序列pcg32_uniqueunique XSH RR64→32唯一流多流并行pcg32_fastmcg XSH RS64→32MCG追求速度、可牺牲流灵活性pcg64setseq XSL RR128→64通用 64 位输出pcg64_oneseqoneseq XSL RR128→64单流确定性 64 位输出pcg64_uniqueunique XSL RR128→64多流并行pcg64_fastmcg XSL RR128→64MCG高速 64 位输出此外还有pcg8/pcg16/pcg32/pcg64/pcg128_once_insecure等小位宽/大位宽变体以及pcg32_k2、pcg64_k32、pcg32_k1024、pcg64_k1024、pcg32_k16384等通过扩展生成方案实现超长周期的家族。选择逻辑可以概括为需要多路可独立播种的流如多线程各自持有一个 RNG时使用setseq/unique系列只关心单一确定序列、希望给定种子后输出完全可复现时使用oneseq系列需要极致吞吐且不要求流隔离时使用_fastMCG系列。Arrow 中的实际使用场景1.random计算内核为什么选pcg64_oneseqArrow 的标量random函数用于生成[0, 1)区间的均匀分布双精度数实现在 cpp/src/arrow/compute/kernels/scalar_random.cc 中。文件开头的注释明确给出了选型理由scalar_random.cc 第 36-42 行不需要多条流因此排除多流设计希望给定种子后输出完全确定因此排除 unique 流生成器pcg64的no-streamMCG/fast生成器对仅低 2 位不同的种子如 0、1、2、3会产生相同输出不满足种子即结果的可复现预期因此排除pcg64_fast。最终选定random::pcg64_oneseq128 位状态、64 位输出、单流 LCG并沿用 numpy 的做法把 64 位输出右移 11 位再乘以1/2^53得到严格小于 1 的双精度随机数scalar_random.cc 第 45-51 行。种子来源分两种模式RandomOptions::Seed时直接使用用户提供的 seed否则在互斥锁保护下用seed_seq_fromstd::random_device构造的全局种子生成器取种子scalar_random.cc 第 61-79 行。该内核注册为标量函数random无参、输出float64、非纯函数对应 Python 侧的pyarrow.compute.random。2. Acero 执行引擎pcg32_fast与哈希分区回退在 Acero 执行引擎的哈希分区锁实现中partition_util.cc 为每个线程分配一个独立的arrow::random::pcg32_fastRNGrngs_.reset(new arrow::random::pcg32_fast[num_threads]); arrow::random::pcg32_fast seed_gen(0); std::uniform_int_distributionuint32_t seed_dist; for (size_t i 0; i num_threads; i) rngs_[i].seed(seed_dist(seed_gen));这里选用pcg32_fast而非pcg32是因为random_int()每次都要通过std::uniform_int_distribution生成一个[0, num_values)内的随机分区编号属于高频调用MCG 变体的低开销优势在这里更有价值同时该函数不要求不同线程输出不同的确定性序列只需互不相关即可。3. TPC‑H 基准数据生成pcg32_fast驱动伪文本TPC‑H 基准的PSEUDO TEXT列需要按确定性规则生成词、短语与句子。tpch_node.cc 中TpchPseudotext的众多GenerateWord、GenerateNoun、GenerateVerb、GenerateSentence等方法均接收random::pcg32_fast rng参数如 tpch_node.cc 第 281-457 行用同一个 RNG 依次消费随机数从而保证相同种子下生成的 TPC‑H 数据完全一致、可复现。随机字符串与电话号码生成RandomVString、GeneratePhoneNumber同样基于该 RNG。使用与构建说明包含头文件Arrow 内部源码统一通过#include arrow/util/pcg_random.h使用该文件再转发到 vendored 头文件如需直接使用原生接口可包含arrow/vendored/pcg/pcg_random.hpp该路径在安装后依然可用因为 CMake 会安装整个 pcg 目录头文件。典型初始化arrow::random::pcg32 rng(seed);或通过pcg_extras::seed_seq_fromstd::random_device构造更高质量的种子序列生成随机数时可直接调用rng()等价于operator()或配合std::uniform_int_distribution、std::uniform_real_distribution等标准分布器使用。平台适配位旋转等底层操作在 GCC/Clang 下走内联汇编在 MSVC 下走_rotr系列内建函数当前仓库已启用 MSVC ARM64 intrinsics因此 Windows ARM64 Visual Studio 构建可获得原生性能路径。许可与归属内嵌代码版权归 Melissa ONeill 与 PCG 项目贡献者所有以 Apache-2.0 或 MIT 任选其一分发README 中保留了来源 changeset 与改动记录便于追溯上游。小结Apache Arrow 通过最小改动 命名空间隔离 版本记录的方式内嵌 PCG 随机数生成器README 记录来源与三处必要修改命名空间、移除arbitrary_seed、MSVC ARM64 intrinsics而引擎能力则由 pcg_random.hpp 的完整 typedef 家族提供。在 Arrow 内部pcg64_oneseq支撑random计算内核的确定性输出pcg32_fast支撑 Acero 分区锁的线程级随机数与 TPC‑H 伪文本生成——理解这两条选型线索就理解了 Arrow 在速度、可复现性与流隔离之间的工程权衡。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价