当前位置: 首页 > article >正文

昇腾CANN cmake 实战:CANN CMake 构建系统——跨平台编译配置与模块化管理

8 个 CANN 仓库各需独立构建ops-transformer/ops-nn/hccl/ge/…→ 手写 8 套 CMakeLists.txtCANN 路径判断、跨 NPU 型号编译、第三方库兼容。cmake 仓库提供统一的FindCANN.cmakeCANNConfig.cmake模板——任何仓库只需find_package(CANN)一行自动推断 toolkit 路径、编译器、依赖库。同时管理 55 个仓库的交叉编译配置。cmake 仓库不仅是一套 CMake 脚本——它是 CANN 全 55 个仓库的统一编译入口。仓库之间的交叉依赖ops-transformer depends on opbase, hccl depends on runtime, …全部通过 CMake 的find_package()target_link_libraries()自动链入开发者不需要关心 CANN 装在哪个目录。CANN CMake 配置体系三层Layer 0: FindCANN.cmake自动查找 CANN 安装路径 ├─ 环境变量 $ASCEND_HOME_PATH ├─ 默认路径探测 (/usr/local/Ascend/...) └─ 包管理器路径 (apt/pip/conda) Layer 1: CANNConfig.cmake导出 CANN 编译配置 ├─ CANN_INCLUDE_DIRS头文件路径 ├─ CANN_LIBRARIES库文件列表 └─ CANN_COMPILE_OPTIONS编译选项--aicore / -DASCEND910 Layer 2: can_target_* 高层构建宏 ├─ can_add_op_target()构建 Ascend C 算子 .so ├─ can_add_test_target()构建 ACL 测试程序 └─ can_add_pybind_target()构建 Python binding# cmake/modules/FindCANN.cmakeLayer 0路径查找 # # 用法find_package(CANN 8.0 REQUIRED COMPONENTS acl ge ascendc) # → CANN_FOUND TRUE # → CANN_INCLUDE_DIRS /usr/local/Ascend/ascend-toolkit/8.0/include # → CANN_LIBRARIES ${CANN_LIB_ACL} ${CANN_LIB_GE} ... # # 自动探测逻辑 # 1. $ASCEND_HOME_PATH → ascend-toolkit → latest # 2. /usr/local/Ascend/ascend-toolkit/latest # 3. /opt/ascend/ascend-toolkit/latest # 4. pip show ascend-toolkit → Location # 5. find_path(find_path → ascendc/ascendc.h) # FindCANN.cmake # ---------- Determine CANN root ---------- set(_CANN_POSSIBLE_ROOTS) # 1. Environment variable if(DEFINED ENV{ASCEND_HOME_PATH}) list(APPEND _CANN_POSSIBLE_ROOTS $ENV{ASCEND_HOME_PATH}) endif() # 2. Default install paths list(APPEND _CANN_POSSIBLE_ROOTS /usr/local/Ascend/ascend-toolkit/latest /opt/ascend/ascend-toolkit/latest $ENV{HOME}/Ascend/ascend-toolkit/latest ) # 3. pip-based install (Python virtual env) execute_process( COMMAND ${Python3_EXECUTABLE} -c import ascend; print(ascend.__path__[0]) RESULT_VARIABLE _pip_ret OUTPUT_VARIABLE _pip_path OUTPUT_STRIP_TRAILING_WHITESPACE ) if(_pip_ret EQUAL 0 AND _pip_path) get_filename_component(_pip_toolkit ${_pip_path}/../../../ ABSOLUTE) list(APPEND _CANN_POSSIBLE_ROOTS ${_pip_toolkit}) endif() # ---------- Find CANN header ---------- find_path(CANN_INCLUDE_DIR NAMES ascendc/ascendc.h PATHS ${_CANN_POSSIBLE_ROOTS} PATH_SUFFIXES include DOC CANN include directory ) if(NOT CANN_INCLUDE_DIR) message(FATAL_ERROR CANN not found. Set $ASCEND_HOME_PATH or install ascend-toolkit) endif() # ---------- Determine CANN version ---------- find_file(_CANN_VERSION_FILE NAMES version.cfg PATHS ${CANN_INCLUDE_DIR}/.. PATH_SUFFIXES ) if(_CANN_VERSION_FILE) file(STRINGS ${_CANN_VERSION_FILE} _version_str REGEX ^version.*$) string(REGEX REPLACE ^version CANN_VERSION ${_version_str}) else() set(CANN_VERSION unknown) endif() message(STATUS Found CANN ${CANN_VERSION} at ${CANN_INCLUDE_DIR}) # ---------- Find CANN libraries ---------- set(CANN_LIB_DIR ${CANN_INCLUDE_DIR}/../lib64) find_library(CANN_LIB_ACL NAMES ascendcl PATHS ${CANN_LIB_DIR} REQUIRED ) find_library(CANN_LIB_GE NAMES ge_runner ge PATHS ${CANN_LIB_DIR} REQUIRED ) find_library(CANN_LIB_RUNTIME NAMES runtime PATHS ${CANN_LIB_DIR} REQUIRED ) # Package components set(CANN_LIBRARIES ${CANN_LIB_ACL} ${CANN_LIB_GE} ${CANN_LIB_RUNTIME} ) # ---------- Determine NPU architecture ---------- # Ascend 910 / 910B / 950PR (detect from device or assume default) execute_process( COMMAND npu-smi info -m -q 1 RESULT_VARIABLE _smi_ret OUTPUT_VARIABLE _smi_out ) if(_smi_ret EQUAL 0) string(REGEX MATCH Ascend[0-9][A-Z]* _soc ${_smi_out}) set(CANN_SOC_VERSION ${_soc}) else() set(CANN_SOC_VERSION Ascend910B) # default endif() message(STATUS NPU: ${CANN_SOC_VERSION}) # ---------- Set compile definitions ---------- set(CANN_COMPILE_DEFINITIONS -DASCEND_DEVICE -D${CANN_SOC_VERSION} ) if(CANN_SOC_VERSION MATCHES 910) list(APPEND CANN_COMPILE_DEFINITIONS -DL1_CACHE_SIZE1048576) # 1MB elseif(CANN_SOC_VERSION MATCHES 950) list(APPEND CANN_COMPILE_DEFINITIONS -DL1_CACHE_SIZE524288) # 512KB endif() set(CANN_FOUND TRUE)# cmake/modules/CANNTargetFunctions.cmakeLayer 2高层宏 # # 提供 can_add_op_target / can_add_test_target / can_add_pybind_target # 封装了所有 Ascend C kernel 编译的 boilerplate include_guard(GLOBAL) # can_add_op_target()构建 Ascend C 算子 .so # # 用法 # can_add_op_target(custom_layer_norm # SOURCES src/kernel.cc op_reg/register.cc # INCLUDE_DIRS include/ # LINK_LIBS opbase hccl # DEVICE_VERSIONS Ascend910B Ascend950PR # 多 NPU 型号 # ) # → libcustom_layer_norm_Ascend910B.so, libcustom_layer_norm_Ascend950PR.so macro(can_add_op_target target_name) cmake_parse_arguments(ARG # no boolean flags # no single-value args SOURCES;INCLUDE_DIRS;LINK_LIBS;DEVICE_VERSIONS # multi-value ${ARGN} ) # 对每个 NPU 型号构建一个 .so foreach(device_version ${ARG_DEVICE_VERSIONS}) set(lib_name ${target_name}_${device_version}) add_library(${lib_name} SHARED ${ARG_SOURCES}) target_include_directories(${lib_name} PRIVATE ${ARG_INCLUDE_DIRS} ${CANN_INCLUDE_DIRS} ${CANN_INCLUDE_DIRS}/ascendc ) # 针对此 NPU 型号的编译选项 target_compile_definitions(${lib_name} PRIVATE ${CANN_COMPILE_DEFINITIONS} -DTARGET_DEVICE${device_version} ) # Ascend C kernel 必须用 Bisheng 编译器 if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) set_property(TARGET ${lib_name} PROPERTY CXX_STANDARD 17 ) # 加 Bisheng 兼容标志 target_compile_options(${lib_name} PRIVATE -fno-strict-aliasing -D__aicore__ ) endif() # 链接 CANN 库 target_link_libraries(${lib_name} ${CANN_LIBRARIES} ${ARG_LINK_LIBS} ) # 安装 install(TARGETS ${lib_name} LIBRARY DESTINATION lib/${device_version} ) message(STATUS ✅ Built ${lib_name} for ${device_version}) endforeach() endmacro() # can_add_test_target()构建 ACL 测试程序 # # 用法 # can_add_test_target(test_layer_norm # SOURCES test/test_main.cc test/test_cases.cc # DEPS custom_layer_norm_Ascend910B # ← 依赖上面构建的 .so # DEVICE_ID 0 # ) macro(can_add_test_target test_name) cmake_parse_arguments(ARG DEVICE_ID SOURCES;DEPS ${ARGN} ) add_executable(${test_name} ${ARG_SOURCES}) target_link_libraries(${test_name} ${ARG_DEPS} ${CANN_LIB_ACL} gtest gtest_main pthread ) # 运行测试自动 set DEVICE_ID add_test( NAME ${test_name} COMMAND ${test_name} --gtest_filter* WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) set_tests_properties(${test_name} PROPERTIES ENVIRONMENT ASCEND_DEVICE_ID${ARG_DEVICE_ID} ) message(STATUS ✅ Test target ${test_name} (NPU#${ARG_DEVICE_ID})) endmacro() # can_add_pybind_target()构建 Python binding # # 用法 # can_add_pybind_target(custom_layer_norm_py # SOURCES python/bindings.cc # DEPS custom_layer_norm_Ascend910B # ) # → custom_layer_norm_py.cpython-38-x86_64-linux-gnu.so macro(can_add_pybind_target target_name) cmake_parse_arguments(ARG SOURCES;DEPS ${ARGN} ) # Find pybind11 find_package(pybind11 REQUIRED) pybind11_add_module(${target_name} ${ARG_SOURCES}) target_link_libraries(${target_name} PRIVATE ${ARG_DEPS} ${CANN_LIBRARIES} ) install(TARGETS ${target_name} LIBRARY DESTINATION python/ ) message(STATUS ✅ Python binding ${target_name}) endmacro()跨仓库构建55 个仓库的统一 CMake 流程# cmake/examples/superbuild.cmakeCANN Super Build # # 一次性构建 55 个仓库的超级构建脚本 # 自动推断仓库间的依赖关系opbase→ops-*hccl→distributedge→framework cmake_minimum_required(VERSION 3.16) project(CANN_SuperBuild LANGUAGES CXX) find_package(CANN 8.0 REQUIRED) include(cmake/modules/CANNTargetFunctions.cmake) # 仓库依赖图 # opbase (layer 0, no deps) # ├── ops-math, ops-nn, ops-blas, ops-cv, ops-fft, ops-rand, ops-tensor # ├── hccl, hcomm, hixl # └── ge, runtime, driver # # ops-transformer (depends on ops-nn, opbase) # ascend-transformer-boost (depends on ops-transformer) # torchtitan-npu (depends on ascend-transformer-boost) # Layer 0: Base dependencies set(OPBASE_DIR ${CMAKE_SOURCE_DIR}/../opbase) add_subdirectory(${OPBASE_DIR} opbase-binary) # Layer 1: Core operators (depend on opbase) foreach(op_repo ops-nn ops-math ops-blas ops-cv ops-fft ops-rand ops-tensor) set(repo_dir ${CMAKE_SOURCE_DIR}/../${op_repo}) if(EXISTS ${repo_dir}) add_subdirectory(${repo_dir} ${op_repo}-binary) message(STATUS ✅ ${op_repo}) endif() endforeach() # Layer 2: Communication (depend on driver) set(HCCL_DIR ${CMAKE_SOURCE_DIR}/../hccl) add_subdirectory(${HCCL_DIR} hccl-binary) set(HCOMM_DIR ${CMAKE_SOURCE_DIR}/../hcomm) add_subdirectory(${HCOMM_DIR} hcomm-binary) set(HIXL_DIR ${CMAKE_SOURCE_DIR}/../hixl) add_subdirectory(${HIXL_DIR} hixl-binary) # Layer 3: Graph engine (depend on opbase driver) set(GE_DIR ${CMAKE_SOURCE_DIR}/../ge) add_subdirectory(${GE_DIR} ge-binary) # Layer 4: Transformer operators (depend on ops-nn opbase) set(OPS_TRANSFORMER_DIR ${CMAKE_SOURCE_DIR}/../ops-transformer) add_subdirectory(${OPS_TRANSFORMER_DIR} ops-transformer-binary) # Build message(STATUS SuperBuild: ${N_REPOS} repos configured, building...)跨 NPU 型号多版本编译910 vs 950 vs 950PR# cmake/examples/build_multi_soc.sh# 同一个算子代码编译出 910 / 950PR 两个 .so# 运行时通过 soc_version 自动加载对应版本ASCEND_TOOLKIT_HOME/usr/local/Ascend/ascend-toolkit/8.0# Ascend 910B mkdir-pbuild_910Bcdbuild_910B cmake..\-DCANN_ROOT${ASCEND_TOOLKIT_HOME}\-DCANN_SOC_VERSIONAscend910B\-DCMAKE_BUILD_TYPEReleasemake-j$(nproc)# → libcustom_op_Ascend910B.socd..# Ascend 950PR mkdir-pbuild_950PRcdbuild_950PR cmake..\-DCANN_ROOT${ASCEND_TOOLKIT_HOME}\-DCANN_SOC_VERSIONAscend950PR\-DCMAKE_BUILD_TYPEReleasemake-j$(nproc)# → libcustom_op_Ascend950PR.socd..# 运行时自动选择 # CANN 根据 aclrtGetDeviceInfo() 返回的 soc_version 自动加载对应 .solslib/# lib/custom_op/Ascend910B/libcustom_op.so# lib/custom_op/Ascend950PR/libcustom_op.so# 无需手动判断ACL 的 op_loader 自动查找匹配的 soc_version 目录打包与分发RPM / Docker# cmake/modules/CANNPackaging.cmake # RPM 打包 set(CPACK_GENERATOR RPM) set(CPACK_PACKAGE_NAME cann-ops-nn) set(CPACK_PACKAGE_VERSION 8.0.1) set(CPACK_PACKAGE_VENDOR Ascend) set(CPACK_RPM_PACKAGE_REQUIRES ascend-toolkit 8.0, opbase 8.0) include(CPack) # 生成 RPM 包 # cmake --build build --target package # → cann-ops-nn-8.0.1-1.x86_64.rpm # DEB 打包 set(CPACK_GENERATOR DEB) set(CPACK_DEBIAN_PACKAGE_DEPENDS ascend-toolkit ( 8.0), libopbase ( 8.0))# cmake/examples/Dockerfile.cann FROM ubuntu:22.04 # Install CANN toolkit COPY ascend-toolkit-8.0.run /tmp/ RUN /tmp/ascend-toolkit-8.0.run --install --quiet # Build all operators (cmake superbuild) WORKDIR /workspace/cann COPY . . RUN mkdir build cd build \ cmake .. \ -DCANN_ROOT/usr/local/Ascend/ascend-toolkit/8.0 \ -DCMAKE_BUILD_TYPERelease \ make -j$(nproc) \ cmake --install . --prefix /opt/cann # Runtime environment ENV LD_LIBRARY_PATH/opt/cann/lib64:/usr/local/Ascend/ascend-toolkit/8.0/lib64 ENV ASCEND_HOME_PATH/usr/local/Ascend/ascend-toolkit/8.0 CMD [/opt/cann/bin/test_all_ops]踩坑一FindCANN 在虚拟环境 pip install 后找不到头文件——Python venv 不是系统级安装# ❌ pip install ascend-toolkit → virtual env ~/.venv/# cmake 探测 /usr/local/Ascend → 不存在 → FATAL ERROR# 因为 find_path 默认扫描系统路径不扫描 virtual env# ✅ 用 Python3_EXECUTABLE 探测 virtual envexecute_process(COMMAND${Python3_EXECUTABLE}-cimport site; print(site.getsitepackages()[0])OUTPUT_VARIABLE _site_packages)list(APPEND _CANN_POSSIBLE_ROOTS${_site_packages}/ascend/toolkit)# 或在 cmake 命令行指定 CANN_ROOTcmake..-DCANN_ROOT~/.venv/lib/python3.8/site-packages/ascend/toolkit踩坑二CMake 多仓库构建中的 link 顺序——opbase.so 被多次链接导致符号表重复55 个仓库都target_link_libraries(... opbase)→ cmake 生成 55 次-lopbase→ ld 把 opbase.so 的符号表复制 55 次 → 最终 .so 膨胀 2.8GB正常 320MB。# ❌ 每个仓库独立 link opbase → 符号重复 # ops-nn/CMakeLists.txt: target_link_libraries(ops_nn opbase) # ops-transformer/CMakeLists.txt: target_link_libraries(ops_transformer ops_nn opbase) # ← opbase 又 link 一次 # ✅ 用 INTERFACE 传递不重复 link # opbase/CMakeLists.txt: add_library(opbase SHARED ...) target_include_directories(opbase INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) # 其他仓库只需要 INTERFACE 依赖不在 link 阶段重复 find_package(opbase CONFIG REQUIRED) target_link_libraries(my_op PRIVATE ${CANN_LIBRARIES} # ← opbase 不重复 link ) target_include_directories(my_op SYSTEM PRIVATE ${OPBASE_INCLUDE_DIRS}) # opbase 在 CANN_LIBRARIES 中已含通过 FindCANN不重复添加踩坑三CMake 构建时 Ascend 910 vs 950 的 Tiling 块大小不兼容——L1_CACHE_SIZE宏在不同 NPU 间不一致# ❌ 硬编码 1MB L1Ascend 910 add_compile_definitions(L1_CACHE_SIZE1048576) # → Ascend 950 的 L1 只有 512KB → Tiling: BM/BN/BK 溢出 L1 → kernel 错误 # ✅ 运行时或编译期判断 NPU 型号 # cmake: if(CANN_SOC_VERSION MATCHES 910) add_compile_definitions(L1_CACHE_SIZE1048576) elseif(CANN_SOC_VERSION MATCHES 950) add_compile_definitions(L1_CACHE_SIZE524288) else() message(WARNING Unknown NPU version: ${CANN_SOC_VERSION}, L1 unknown) add_compile_definitions(L1_CACHE_SIZE1048576) # fallback endif() # 或用 AutoTiling 运行时判断不用编译期宏 // In kernel code: __aicore__ void MatMulKernel(...) { // 运行时获取 L1 大小 int l1_size GetL1CacheSize(); // 910 → 1048576, 950 → 524288 auto config AutoTiling::Compute(M, N, K, l1_size); // ... }cmake 仓库是 CANN 全 55 个仓库的统一编译入口。FindCANN.cmake 自动探测 CANN 安装路径环境变量→默认路径→pip虚拟环境→包管理器、CANNTargetFunctions 提供can_add_op_target/can_add_test_target/can_add_pybind_target三个高层次构建宏封装 Ascend C kernel 编译 ACL 测试运行 Python binding、SuperBuild 自动推断 55 个仓库的依赖图opbase→ops-*→transformer→ATB→torchtitan。三个踩坑pip venv 不被 cmake 扫描→用 Python3 探 site-packages、55 个仓库独立 link opbase→符号重复膨胀 2.8GB→用 INTERFACE 传递、910/950 L1 大小不兼容→编译期if(CANN_SOC_VERSION)或运行时 AutoTiling。

相关文章:

昇腾CANN cmake 实战:CANN CMake 构建系统——跨平台编译配置与模块化管理

8 个 CANN 仓库各需独立构建(ops-transformer/ops-nn/hccl/ge/…)→ 手写 8 套 CMakeLists.txt(CANN 路径判断、跨 NPU 型号编译、第三方库兼容)。cmake 仓库提供统一的 FindCANN.cmake CANNConfig.cmake 模板——任何仓库只需 f…...

3步零基础掌握星露谷物语SMAPI模组加载器:高效管理你的模组世界

3步零基础掌握星露谷物语SMAPI模组加载器:高效管理你的模组世界 【免费下载链接】SMAPI The modding API for Stardew Valley. 项目地址: https://gitcode.com/gh_mirrors/smap/SMAPI SMAPI(Stardew Valley Modding API)是星露谷物语官…...

YOLOv8道路交通信号标志识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置)

摘要 道路交通信号标志的自动检测是智能驾驶与交通管理系统中的核心环节。本文基于YOLOv8目标检测算法,构建了一个涵盖21类常见交通信号标志的检测系统,包括禁令标志、指示标志、警告标志及信号灯等。模型在包含1376张训练图像、488张验证图像和229张测…...

昇腾CANN elec-ops-simulation 实战:电力系统仿真——潮流计算与暂态稳定分析在 NPU 上的加速

电力系统仿真&#xff1a;500 节点电网的牛顿-拉夫逊潮流计算 → 解 10001000 稀疏雅可比矩阵&#xff08;每迭代 1 次矩阵求逆&#xff09;→ CPU 迭代 15 次 2.4s。实时调度要求 < 100ms → NPU 加速&#xff1a;雅可比矩阵求解用 Cube 单元做批量小矩阵 LU 分解 → 每迭…...

3步开启Windows 11安卓应用新体验:WSA完整使用指南

3步开启Windows 11安卓应用新体验&#xff1a;WSA完整使用指南 【免费下载链接】WSA Developer-related issues and feature requests for Windows Subsystem for Android 项目地址: https://gitcode.com/gh_mirrors/ws/WSA Windows Subsystem for Android&#xff08;简…...

Awoo Installer:让Switch游戏安装变得简单高效的终极解决方案

Awoo Installer&#xff1a;让Switch游戏安装变得简单高效的终极解决方案 【免费下载链接】Awoo-Installer A No-Bullshit NSP, NSZ, XCI, and XCZ Installer for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/aw/Awoo-Installer 厌倦了繁琐的Switch游戏安…...

Claude Code + LM Studio + CC-Switch 本地自动化编程部署指南

Claude Code LM Studio CC-Switch 本地自动化编程部署指南 本指南汇总了在 Windows 本地环境下&#xff0c;使用 Claude Code 配合 LM Studio 本地模型、CC-Switch 代理进行自动化编程开发的完整配置方案。 目录 硬件与模型选型LM Studio 本地模型部署CC-Switch 代理配置Cla…...

Windows 11 LTSC安装微软商店的终极解决方案:3步恢复完整应用生态

Windows 11 LTSC安装微软商店的终极解决方案&#xff1a;3步恢复完整应用生态 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore LTSC-Add-MicrosoftStor…...

AICoverGen终极指南:快速创建AI翻唱歌曲的完整教程

AICoverGen终极指南&#xff1a;快速创建AI翻唱歌曲的完整教程 【免费下载链接】AICoverGen A WebUI to create song covers with any RVC v2 trained AI voice from YouTube videos or audio files. 项目地址: https://gitcode.com/gh_mirrors/ai/AICoverGen 想要让你的…...

为什么你的霓虹总像“塑料灯带”?Midjourney光子散射模拟缺陷曝光:3个被官方隐瞒的--sref调参禁区

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;为什么你的霓虹总像“塑料灯带”&#xff1f; 霓虹效果在现代 UI 设计中无处不在——按钮悬停、加载指示器、焦点高亮……但多数实现却流于表面&#xff1a;生硬的 box-shadow、固定色值的渐变边框、缺乏物理感…...

揭秘Midjourney云雾渲染失效真相:3大隐性提示词冲突、2类SDXL迁移兼容漏洞及实时雾浓度校准公式

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;揭秘Midjourney云雾渲染失效真相&#xff1a;3大隐性提示词冲突、2类SDXL迁移兼容漏洞及实时雾浓度校准公式 Midjourney V6 在启用云雾&#xff08;mist/fog/haze&#xff09;类视觉效果时&#xff0c;…...

DeepSeek-R1代码补全实测报告:37个真实项目、8类编程语言、48小时压测后,我删掉了Copilot

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;DeepSeek-R1代码补全实测报告总览 DeepSeek-R1 是深度求索&#xff08;DeepSeek&#xff09;推出的开源大语言模型&#xff0c;专为代码理解与生成任务优化。本章聚焦其在主流 IDE 环境中代码补全能力的…...

PostgreSQL Merge Join 大白话详解

用生活中最直观的例子&#xff0c;彻底搞懂 Merge Join 是什么、为什么快、什么时候用。一、先从生活场景开始 场景一&#xff1a;两摞乱序试卷找同学 期末考试&#xff0c;老师手里有两摞试卷&#xff1a; A 摞&#xff1a;数学试卷&#xff0c;500 份&#xff0c;乱序堆放B 摞…...

PostgreSQL Join 执行策略(Nested Loop、Hash Join、Merge Join)与 NOT EXISTS 优化

以集成数据压缩 SQL 优化为例&#xff0c;用大白话讲清楚 Nested Loop、Hash Join、Merge Join 三种执行策略。一、背景&#xff1a;一条慢 SQL 引发的思考 在对上游下发数据做压缩时&#xff0c;有这样一条 UPDATE SQL&#xff1a; -- ❌ 原始写法 UPDATE magellan_nk_order_i…...

Godot 2D随机地图三大静默故障:黑屏、穿墙、寻路失败的根源与修复

1. 为什么刚上手Godot做2D随机地图就总卡在“生成出来是黑的”“角色穿墙”“房间连不通”这三件事上&#xff1f;如果你是刚从Unity或GameMaker转来Godot&#xff0c;或者第一次用GDScript写程序逻辑的新手&#xff0c;大概率已经在2D随机地图生成这个环节反复摔过跟头——不是…...

基于Arduino Uno与MQ-2传感器的智能气体检测报警系统DIY全攻略

1. 项目概述与核心思路最近在捣鼓家里的智能安防&#xff0c;琢磨着能不能自己做一个成本可控、反应灵敏的气体检测报警装置。市面上成品烟雾报警器虽然成熟&#xff0c;但要么功能单一&#xff0c;要么价格不菲&#xff0c;而且很难根据自己的需求进行定制化调整&#xff0c;比…...

泰拉瑞亚地图编辑器:从像素画布到创意世界的蜕变之旅

泰拉瑞亚地图编辑器&#xff1a;从像素画布到创意世界的蜕变之旅 【免费下载链接】Terraria-Map-Editor TEdit - Terraria Map Editor - TEdit is a stand alone, open source map editor for Terraria. It lets you edit maps just like (almost) paint! It also lets you cha…...

机器学习赋能矩方法:破解稀薄气体强非平衡流动模拟难题

1. 项目概述&#xff1a;当矩方法遇见机器学习在计算流体力学领域&#xff0c;模拟稀薄气体动力学和强非平衡流动&#xff0c;一直是个让工程师和科学家们头疼的“硬骨头”。想象一下&#xff0c;你正在设计一架高超音速飞行器&#xff0c;当它以数倍音速在大气层边缘飞行时&am…...

Godot 4.3随机地图性能优化:避开TileMap与RNG陷阱

1. 为什么刚写完第一版随机地图就崩溃&#xff1f;——从“能跑”到“能用”的真实断层你兴冲冲地照着教程敲完几十行GDScript&#xff0c;RandomNumberGenerator初始化了&#xff0c;for x in range(width)循环也套好了&#xff0c;甚至还在_draw()里用draw_rect()把每个格子都…...

告别复杂模型:用Python+OpenCV+dlib实现简易驾驶员疲劳监测(附完整代码)

轻量级驾驶员疲劳监测系统&#xff1a;PythonOpenCVdlib实战指南 在长途驾驶或夜间行车时&#xff0c;疲劳是导致交通事故的重要因素之一。传统基于嵌入式设备的疲劳监测系统往往需要专用硬件&#xff0c;增加了开发成本和部署难度。本文将介绍如何利用Python生态中的OpenCV和d…...

NPU跑LLM实战指南:KV Cache动态性如何突破硬件限制

NPU跑LLM实战指南:KV Cache动态性如何突破硬件限制 副标题: 从预分配+Attention Mask到三层软件栈,完整解析NPU推理架构 痛点:为什么NPU跑LLM这么难? LLM的生成机制和NPU的硬件特性存在根本冲突: LLM特性 NPU特性 冲突点 逐token生成 固定shape执行 KV Cache动态增长 动…...

如何用Untrunc拯救损坏视频?2025年终极MP4修复工具完全指南

如何用Untrunc拯救损坏视频&#xff1f;2025年终极MP4修复工具完全指南 【免费下载链接】untrunc Restore a damaged (truncated) mp4, m4v, mov, 3gp video. Provided you have a similar not broken video. 项目地址: https://gitcode.com/gh_mirrors/unt/untrunc 当你…...

基于ISDN信令的来电语音播报系统:从原理到树莓派实现

1. 项目概述&#xff1a;一个基于ISDN的来电语音播报系统如果你家里或办公室里还有一台老式的ISDN路由器&#xff0c;别急着把它当电子垃圾处理掉。我最近就利用手头一台闲置的ISDN路由器&#xff0c;折腾出了一个挺有意思的小玩意儿&#xff1a;一个能自动识别来电号码&#x…...

纯硬件实现I2C协议:从逻辑门到传感器通信的深度实践

1. 项目概述&#xff1a;用纯硬件“解剖”I2C总线很多朋友在玩传感器&#xff0c;尤其是温湿度传感器时&#xff0c;都绕不开I2C这个通信协议。市面上绝大多数的教程和方案&#xff0c;都会告诉你&#xff1a;找个单片机&#xff08;比如Arduino、STM32&#xff09;&#xff0c…...

Python Android打包终极指南:5个实战技巧解决移动开发痛点

Python Android打包终极指南&#xff1a;5个实战技巧解决移动开发痛点 【免费下载链接】python-for-android Turn your Python application into an Android APK 项目地址: https://gitcode.com/gh_mirrors/py/python-for-android Python-for-Android&#xff08;简称p4…...

为什么你明明很努力,领导却总看不到?问题出在这

许多测试同行在深夜加班排查Bug时&#xff0c;在凌晨赶写自动化脚本时&#xff0c;在对着海量数据做性能分析时&#xff0c;内心都会浮现一个共同的困惑&#xff1a;我明明已经这么拼了&#xff0c;为什么在领导眼里&#xff0c;我依然是个“找茬的”&#xff0c;而不是“创造价…...

ROS机器人仿真架构解析:基于wpr_simulation的移动操作机器人技术实现

ROS机器人仿真架构解析&#xff1a;基于wpr_simulation的移动操作机器人技术实现 【免费下载链接】wpr_simulation 项目地址: https://gitcode.com/gh_mirrors/wp/wpr_simulation 在机器人操作系统(ROS)开发领域&#xff0c;硬件依赖和测试成本一直是制约算法迭代效率的…...

ImageGlass:一个支持90+图像格式的轻量级Windows图片查看器

ImageGlass&#xff1a;一个支持90图像格式的轻量级Windows图片查看器 【免费下载链接】ImageGlass &#x1f3de; A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass 还在为Windows自带的图片查看器功能单一而烦恼吗&…...

JavaScript对象创建:告别繁琐,四种灵活写法一学就会

在JavaScript里&#xff0c;创建对象的这般方法常把刚开始学习的新手弄得困惑不已&#xff0c;好像无论走哪条道都行得通&#xff0c;可又不清楚该挑哪一条才好。我编写JavaScript都有十几年功夫了&#xff0c;对象创建这事差不多每天都会碰到可谓基础技能。它不像变量声明那般…...

终极崩坏星穹铁道自动化指南:3分钟掌握解放双手的智能游戏伴侣

终极崩坏星穹铁道自动化指南&#xff1a;3分钟掌握解放双手的智能游戏伴侣 【免费下载链接】StarRailAssistant 崩坏&#xff1a;星穹铁道自动化 | 崩坏&#xff1a;星穹铁道自动锄大地 | 崩坏&#xff1a;星穹铁道锄大地 | 自动锄大地 | 基于模拟按键 项目地址: https://git…...