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

PyTorch 分布式 DistributedDataParallel (DDP)

在之前的讨论(或者如果你直接跳到这里)中,我们了解了 torch.nn.DataParallel (DP) 作为 PyTorch 多 GPU 训练的入门选项。它简单易用,但其固有的主 GPU 瓶颈、GIL 限制和低效的通信模式,往往让它在实际应用中难以充分发挥多 GPU 的威力。

那么,当我们追求极致的训练速度、需要扩展到更多 GPU 甚至跨多个节点进行训练时,应该选择什么呢?答案就是 torch.nn.parallel.DistributedDataParallel (DDP)。DDP 是 PyTorch 官方推荐的、用于严肃的分布式训练场景的首选方案。

它虽然比 DP 设置起来稍显复杂,但带来的性能提升和可扩展性是巨大的。这篇博客将带你深入 DDP 的核心,彻底理解它的工作原理、关键组件、与 DP 的本质区别,以及它如何借助 NCCL 等后端实现高效通信,助你真正释放分布式计算的潜力。

一、 DDP 的核心思想:去中心化协作,高效同步

想象一下 DP 是一个“经理-员工”模式:经理(主 GPU)分发任务、收集结果、汇总反馈、独自更新计划。而 DDP 则更像一个高度协同的专家团队

  1. 独立工作区 (多进程): 每个专家(一个独立的 Python 进程)有自己的完整工作区(独立的进程空间和 Python 解释器),负责自己的一部分任务(数据子集)和一套完整的工具(模型副本)。这避免了 Python GIL 的全局限制。
  2. 任务分配 (DistributedSampler): 有一个公平的任务分配机制(DistributedSampler),确保每个专家拿到的任务(数据)是不同的,并且在不同轮次(Epoch)中可以有不同的随机分配。
  3. 并行执行: 所有专家并行地使用自己的工具处理自己的任务(前向传播、计算本地梯度)。
  4. 高效沟通 (AllReduce via NCCL/Gloo): 当需要同步工作成果(梯度)时,专家们不都向某一个人汇报,而是通过一个高效的环状或树状沟通网络 (AllReduce) 互相传递信息,最终每个人都计算出完全相同平均反馈(平均梯度)。这个沟通网络由 NCCL 或 Gloo 等后端库负责高效执行。
  5. 同步更新: 每个专家根据这个共同协商出的平均反馈独立地更新自己手中的那份计划书(更新本地模型参数)。由于使用的反馈完全一致,所有计划书(模型副本)始终保持同步。

这个模式的关键在于:没有中心瓶颈、进程独立、高效的集体通信 (AllReduce)、所有参与者同步更新。

二、 DDP 与 DP 的本质区别 (划重点)

在深入细节之前,我们先明确 DDP 与 DP 最核心的不同:

特性nn.DataParallel (DP)nn.DistributedDataParallel (DDP)关键影响
进程模型单进程,多线程多进程 (每个 GPU 一个独立进程)DDP 避免 Python GIL 瓶颈,真正的并行
通信原语Scatter (数据), Gather (输出), Sum (梯度)AllReduce (梯度同步)AllReduce 更高效、负载均衡,避免单点瓶颈
负载均衡主 GPU 负载极高 (瓶颈)负载相对均衡DDP 能更好地利用所有 GPU 算力,加速比更高
模型更新只在主 GPU 更新,然后复制每个进程独立更新 (使用同步后的梯度)DDP 更新更直接
初始化简单包装 nn.DataParallel(model)需要初始化进程组 (init_process_group)DDP 设置稍复杂,但提供了灵活性(后端、多节点)
数据加载手动切分或默认行为 (可能不均)需要使用 DistributedSamplerDDP 通过 Sampler 保证数据不重叠、公平分配
后端支持内部实现 (基于 CUDA copy)可选后端: NCCL (GPU 高性能), Gloo (CPU/跨平台)DDP 可利用 NCCL 的硬件加速 (NVLink, RDMA)
适用场景单机少量 GPU 快速原型单机多 GPU、多机多 GPU 高性能训练DDP 是可扩展、高性能分布式训练的标准

三、 深入 DDP 的内部机制 (Step-by-Step)

现在,让我们详细拆解一个典型的 DDP 训练迭代流程(假设使用 NCCL 后端):

前提:

  • 你的程序通过 torchrun 或类似的启动器以多进程方式启动,每个进程负责一个 GPU。
  • 环境变量如 RANK, WORLD_SIZE, LOCAL_RANK, MASTER_ADDR, MASTER_PORT 等已被正确设置。
  • 你在每个进程中执行 Python 脚本。

一个训练迭代的流程:

  1. 初始化进程组 (dist.init_process_group(backend="nccl")):

    • 这是 DDP 的第一步也是最关键的一步。每个进程都会执行这个调用。
    • backend="nccl": 指定使用 NCCL 作为 GPU 间通信库。
    • 内部发生:
      • Rendezvous (集合点): 进程们需要互相找到对方。PyTorch 使用 c10d (Collective Operations 10 Distributed) 库提供的机制。通常通过环境变量 MASTER_ADDRMASTER_PORT 指定一个“主节点”地址和端口(Rank 0 进程通常监听此端口),其他进程连接到这个地址进行“报到”。所有进程报到成功后,交换彼此的连接信息(例如,各自的 IP 地址和用于通信的临时端口)。torchrun 极大地简化了这个过程。
      • NCCL 初始化: 一旦进程间建立了初步联系,PyTorch 后端会调用 NCCL 的初始化函数。每个进程获取一个唯一的 NCCL ID (ncclUniqueId,通常由 Rank 0 生成并通过 c10d 广播),然后调用 ncclCommInitRank 加入包含 WORLD_SIZE 个成员的 NCCL 通信域 (ncclComm_t)。NCCL 底层会探测硬件拓扑,选择最优通信策略(Ring/Tree),并建立必要的内部连接。
    • 结果: 所有参与的进程形成了一个通信组,并且知道如何通过 NCCL 互相发送和接收数据。
  2. 模型准备与移动:

    • 每个进程独立地加载模型结构 (model = YourModel(...))。
    • 将模型移动到当前进程对应的 GPU: model.to(device),其中 device 是通过 local_rank 确定的。例如,device = torch.device("cuda", local_rank)
    • 重要区别: 与 DP 不同,模型不是在每次迭代中从主 GPU 复制过来的。每个进程在启动时就有自己独立的模型副本,并且会独立维护它。
  3. DDP 包装 (model = nn.DistributedDataParallel(model, device_ids=[local_rank], output_device=local_rank)):

    • 将本地模型用 DDP 包装器包裹起来。
    • DDP 包装器的工作:
      • 参数广播 (可选但默认): 在初始化时,DDP 会默认将 Rank 0 进程的模型参数广播给所有其他进程。这确保了训练开始时所有模型副本的状态是完全一致的。这是一个 NCCL Broadcast 操作。
      • 注册 Autograd Hooks: 与 DP 类似,DDP 会在模型参数的梯度计算完成后注册钩子函数,但其内部逻辑完全不同,是为了触发 AllReduce
      • 管理梯度分桶 (Bucketing): 为了效率,DDP 会自动将多个参数的梯度放入同一个“桶”中,一次性进行 AllReduce。桶的大小和参数分组可以影响性能。
      • 同步模型缓冲区 (Buffers): 除了参数,模型可能还有缓冲区(例如 BatchNorm 的 running mean/var)。DDP 也会在训练开始和每次前向传播时确保这些缓冲区在所有进程间同步(通常也是通过 Broadcast)。
  4. 数据准备 (DistributedSamplerDataLoader):

    • train_sampler = DistributedSampler(train_dataset, ...): 创建分布式采样器。
      • 关键作用: 根据 world_size 和当前进程的 rank,它只从完整数据集中选择一个不重叠的子集给当前进程。这保证了每个数据样本在一个 Epoch 中只被一个 GPU 处理一次。
      • shuffle=True: 可以在每个 Epoch 开始时(通过 train_sampler.set_epoch(epoch))打乱整个数据集的索引,然后再进行分割,实现分布式环境下的有效随机化。
    • train_dataloader = DataLoader(train_dataset, sampler=train_sampler, batch_size=...): 创建 DataLoader 时传入 sampler。注意: shuffle 参数必须为 False,因为 shuffle 的功能已经由 DistributedSampler 完成了。
  5. 前向传播 (outputs = model(**batch)):

    • 每个进程从自己的 DataLoader 获取一个 不同的 数据批次 batch
    • batch 数据移动到当前进程的 GPU。
    • 执行模型(DDP 包装器)的前向计算。这一步与单 GPU 或 DP 类似,主要是在本地 GPU 上进行计算。
  6. 损失计算 (loss = criterion(outputs, batch["labels"])):

    • 每个进程根据本地的输出和标签计算本地的损失值 loss
  7. 反向传播 (loss.backward()): DDP 的核心魔法发生于此!

    • 调用 loss.backward() 触发 Autograd 引擎。
    • 当计算图中某个参数的梯度被计算出来后,DDP 注册的钩子函数被触发。
    • 梯度聚合与同步:
      • 钩子函数将计算好的梯度放入预先定义好的梯度桶 (bucket) 中。
      • 当一个桶满了(或者到达反向传播的末尾),DDP 会异步地启动一个 NCCL AllReduce 操作来处理这个桶中的所有梯度。
      • NCCL AllReduce 执行:
        • NCCL 使用高效算法(如 Ring AllReduce)在所有 WORLD_SIZE 个 GPU 之间进行通信。
        • 每个 GPU 将自己桶中的梯度数据发送给“邻居”,同时接收来自另一个“邻居”的数据。
        • 在数据传递过程中或之后进行求和 (SUM) 操作。
        • 经过一轮或多轮通信后,每个 GPU 都得到了所有 GPU 对应梯度桶数据的总和
        • DDP 的钩子函数通常会自动将这个总和除以 world_size,得到平均梯度
        • 这个平均梯度覆盖掉该 GPU 上原本计算出的本地梯度。
      • 计算与通信重叠: DDP 的设计允许在计算后面参数的梯度时,同时进行前面梯度桶的 NCCL AllReduce 通信。这极大地隐藏了通信延迟,是 DDP 高性能的关键之一。
    • 结果: loss.backward() 执行完毕后,每个进程的模型副本的 .grad 属性中存储的都是完全相同的、全局平均的梯度。
  8. 优化器更新 (optimizer.step()):

    • 每个进程独立地调用其本地优化器(该优化器作用于本地模型副本的参数)。
    • 由于所有进程的梯度都已被同步为全局平均梯度,所以每个优化器执行 step() 时进行的参数更新是完全一致的。
    • 这保证了在每一步之后,所有模型副本的参数保持同步。

四、 图解 Ring AllReduce (DDP 中常用的梯度同步方式)

想象 4 个 GPU (P0, P1, P2, P3) 组成一个环:

graph LRsubgraph Ring AllReduce for Gradient SyncP0 -- Chunk 0 --> P1;P1 -- Chunk 1 --> P2;P2 -- Chunk 2 --> P3;P3 -- Chunk 3 --> P0;P1 -- Chunk 0 (processed) --> P2;P2 -- Chunk 1 (processed) --> P3;P3 -- Chunk 2 (processed) --> P0;P0 -- Chunk 3 (processed) --> P1;P2 -- Chunk 0 (processed) --> P3;P3 -- Chunk 1 (processed) --> P0;P0 -- Chunk 2 (processed) --> P1;P1 -- Chunk 3 (processed) --> P2;P3 -- Chunk 0 (final) --> P0;P0 -- Chunk 1 (final) --> P1;P1 -- Chunk 2 (final) --> P2;P2 -- Chunk 3 (final) --> P3;endNote -->|"1. Scatter-Reduce: Grad chunks travel around ring, accumulating partial sums."| RingNote2 -->|"2. AllGather: Accumulated sums travel around again until everyone has the total sum."| Ring
  • Scatter-Reduce 阶段: 每个 GPU 将自己的梯度分成 N 块 (N=world_size)。在每一步,它将自己的一块发送给下一个 GPU,同时接收来自上一个 GPU 的一块,并将接收到的块与自己本地对应块的累加值相加。这个过程重复 N-1 次。
  • AllGather 阶段: 现在每个 GPU 都拥有最终总和的一部分。再次进行 N-1 轮传递,每个 GPU 将自己拥有的最终结果块传递给下一个 GPU,直到所有 GPU 都拥有了所有块的最终总和。
  • NCCL 优化: NCCL 对这个过程进行了高度优化,例如流水线操作、利用 NVLink/RDMA 等,实际执行远比这个简化描述高效。

五、 DDP 的关键组件再强调

  • torch.distributed.init_process_group: 建立进程间的通信基础,初始化后端 (NCCL)。
  • torch.nn.parallel.DistributedDataParallel: 核心包装器,负责模型/缓冲区的初始同步、注册 Autograd Hooks 以触发梯度 AllReduce、管理梯度分桶和通信计算重叠。
  • torch.utils.data.distributed.DistributedSampler: 保证数据在多进程间正确、不重叠地划分。
  • 后端库 (NCCL): 底层的通信引擎,负责执行高效的 AllReduce 等集合操作,是 DDP 高性能的关键。

六、 DDP 的优势总结

  • 高性能: 通过高效的 AllReduce 和计算通信重叠,显著减少通信开销。
  • 负载均衡: 所有 GPU 参与计算和通信,负载相对均衡,避免单点瓶颈。
  • 无 GIL 限制: 多进程架构充分利用多核 CPU 处理数据加载等任务。
  • 可扩展性好: 不仅适用于单机多 GPU,更能无缝扩展到多机多 GPU 的大规模集群。
  • 功能更全: 支持更复杂的操作,如同步 BatchNorm 统计量等。

七、 使用 DDP 的注意事项

  • 设置稍复杂: 需要正确处理进程启动、初始化、Sampler 配置。
  • 多进程调试: 调试多进程程序比单进程更困难。
  • 保存/加载模型: 需要特别注意,通常只在 Rank 0 进程保存模型状态,加载时需要确保所有进程加载相同的状态(可以使用 load_state_dict 后进行广播或确保 DDP 自动同步)。
  • 资源需求: 每个进程都需要一定的 CPU 内存和系统资源。

八、 结论

torch.nn.parallel.DistributedDataParallel (DDP) 是 PyTorch 生态系统中实现高性能、可扩展分布式训练的事实标准。它通过采用多进程架构避免了 GIL 限制,利用高效的后端库 (如 NCCL) 执行优化的 AllReduce 操作进行梯度同步,并实现了计算与通信的重叠,从而克服了 nn.DataParallel 的诸多瓶颈。

虽然 DDP 的学习曲线比 DP 稍陡峭,但理解其去中心化协作、高效同步的核心思想,掌握进程组初始化、DDP 包装器、分布式采样器这几个关键组件的用法,你就能驾驭这个强大的工具,显著加速你的模型训练过程,并为迈向更大规模的分布式计算打下坚实的基础。对于任何需要充分利用多 GPU 或进行跨节点训练的严肃任务,投入时间学习和使用 DDP 都是非常值得的。

相关文章:

PyTorch 分布式 DistributedDataParallel (DDP)

在之前的讨论(或者如果你直接跳到这里)中,我们了解了 torch.nn.DataParallel (DP) 作为 PyTorch 多 GPU 训练的入门选项。它简单易用,但其固有的主 GPU 瓶颈、GIL 限制和低效的通信模式,往往让它在实际应用中难以充分发…...

精益数据分析(14/126):基于数据洞察优化产品与运营

精益数据分析(14/126):基于数据洞察优化产品与运营 在创业和数据分析的道路上,我们都在不断摸索前行。我一直希望能和大家共同学习、共同进步,所以今天继续为大家解读《精益数据分析》。这次我们将深入探讨HighScore …...

flutter 插件收集

2025年 1月10号Flutter插件手机 声音转文字 speech_to_text | Flutter package 文字转声音 flutter_tts | Flutter package 堆栈信息 stack_trace | Dart package 跳转到app设置里面 app_settings | Flutter package 轻松的动画 animations | Flutter package 日志打印 t…...

WPF特性分析

文章目录 WPF特性全面分析与性能优化指南引言WPF核心特性1. 声明式UI与XAML2. 硬件加速渲染3. 数据绑定与MVVM4. 样式与模板5. 动画系统 WPF与其他框架比较WPF vs. WinFormsWPF vs. UWPWPF vs. MAUI WPF性能优化最佳实践1. 内存管理优化2. UI虚拟化3. 使用冻结对象4. 减少视觉树…...

3.1goweb框架gin下

Gin 框架有内置的模板引擎,它允许你将数据和 HTML 模板结合,动态生成网页内容。 模板引擎基础使用 单模板文件示例 以下是一个简单的使用单个 HTML 模板文件的示例,展示了如何在 Gin 中渲染模板: package mainimport ("g…...

【全解析】深入理解 JavaScript JSON 数据解析

一、JSON 概述 1. 概念 JSON 全称为 JavaScript Object Notation,是一种轻量级的数据交换格式。它是 JavaScript 中用于描述对象数据的语法的扩展。不过并不限于与 JavaScript 一起使用。它采用完全独立于语言的文本格式,这些特性使 JSON 成为理想的数…...

影刀RPA怎么和AI结合,制作自动采集小红书爆款文章+自动用AI改写标题、内容+用AI文生图生成发文图片+自动在小红书上发布文章

环境: 影刀5.26.24 Win10专业版 doubao deepseek r1 wps 问题描述: 影刀RPA怎么和AI结合,制作自动采集小红书爆款文章+自动用AI改写标题、内容+用AI文生图生成发文图片+自动在小红书上发布文章,最后上传到飞书备份 解决方案: 1.主要流程如下: 全局变量设置(关键…...

懒人一键搭建符号执行环境V5K3

0.背景 在写完上一篇文章后发现,其实V5k3的组合也可以使用。Verilator v5.x 系列版本完全支持本项目的编译与仿真。 不同于 v3 版本,Verilator v5 引入了更严格的访问控制机制:要从 Verilator 生成的 C 仿真模型中访问内部信号或变量&#x…...

Java队列(Queue)核心操作与最佳实践:深入解析与面试指南

文章目录 概述一、Java队列核心实现类对比1. LinkedList2. ArrayDeque3. PriorityQueue 二、核心操作API与时间复杂度三、经典使用场景与最佳实践场景1:BFS层序遍历(树/图)场景2:滑动窗口最大值(单调队列) …...

Android 中实现图片翻转动画(卡片翻转效果)

1、简述 通过 ObjectAnimator 和 AnimatorSet 可以实现图片的翻转动画,并在翻转过程中切换图片,同时避免图片被镜像。 ObjectAnimator 是 Android 动画框架中的一个类,用于对对象的属性进行动画效果处理。它通过改变对象的属性值来实现动画效果,非常适合实现复杂的动画,如…...

智能电网第1期 | 工业交换机在变电站自动化系统中的作用

随着智能电网建设的加速推进,变电站自动化系统对通信网络的实时性、可靠性和安全性提出了更高要求。在变电站智能化改造过程中,传统网络架构面临诸多挑战: 多协议兼容难题:继电保护、测控装置等设备通信协议多样,难以统…...

01.浏览器自动化webdriver源码分析之启动函数

日后,网络爬虫也好,数据采集也好,自动化必然是主流。因此,笔者未雨绸缪,在此研究各类自动化源码,希望能够赶上时代,做出一套实用的自动化框架。 这里先研究传统的webdriver中转来进行浏览器自动…...

day35图像处理OpenCV

文章目录 一、图像预处理17 直方图均衡化17.1绘制直方图17.2直方图均衡化1. 自适应直方图均衡化2. 对比度受限的自适应直方图均衡化3. 示例 19 模板匹配 一、图像预处理 17 直方图均衡化 直方图:反映图像像素分布的统计图,横坐标就是图像像素的取值&…...

精益数据分析(15/126):解锁数据分析关键方法,驱动业务增长

精益数据分析(15/126):解锁数据分析关键方法,驱动业务增长 在创业与数据分析的征程中,我们都在努力探寻成功的密码。今天,我依旧带着和大家共同进步的初衷,深入解读《精益数据分析》的相关内容…...

JETBRAINS USER AGREEMENT【2025.4.16】更新用户许可协议

JETBRAIN旗下的各产品更新用户许可协议: 大致跟漂亮国出口管制政策有关,以下是详细内容: JETBRAINS USER AGREEMENT Version 2.0, effective as of April 16, 2025 THIS IS A LEGAL AGREEMENT. BY CLICKING ON THE "I AGREE" (OR…...

【数字图像处理】立体视觉基础(1)

成像 成像过程:三维空间坐标到二维图像坐标的变换 相机矩阵:建立三维到二维的投影关系 相机的使用步骤(模型-视图变换): (1)视图变换 (2)模型变换 (3&…...

通过AI工具或模型创建PPT的不同方式详解,结合 Assistants API、DALL·E 3 等工具的功能对比及表格总结

以下是通过AI工具或模型创建PPT的不同方式详解,结合 Assistants API、DALLE 3 等工具的功能对比及表格总结: 1. 主要实现方式详解 1.1 基于文本生成PPT 工具示例:Microsoft PowerPoint Copilot、Google Workspace(AI-powered D…...

weibo_har鸿蒙微博分享,单例二次封装,鸿蒙微博,微博登录

weibo_har鸿蒙微博分享,单例二次封装,鸿蒙微博 HarmonyOS 5.0.3 Beta2 SDK,原样包含OpenHarmony SDK Ohos_sdk_public 5.0.3.131 (API Version 15 Beta2) 🏆简介 zyl/weibo_har是微博封装使用,支持原生core使用 &a…...

C++ Lambda表达式复习

C Lambda表达式 (C Lambda Expressions: Beginner to Advanced) Lambda表达式是C11引入的一种轻量级匿名函数语法,支持闭包捕获,可以简化代码逻辑,特别是在函数式编程、回调函数和STL算法场景中尤为常用。本文将从基础语法到高级应用&#x…...

鸿蒙NEXT开发权限工具类(申请授权相关)(ArkTs)

import abilityAccessCtrl, { Permissions } from ohos.abilityAccessCtrl; import { bundleManager, common, PermissionRequestResult } from kit.AbilityKit; import { BusinessError } from ohos.base; import { ToastUtil } from ./ToastUtil;/*** 权限工具类(…...

1000 QPS 下 MySQL 性能瓶颈解决方案

当 MySQL 在 1000 QPS 时出现性能瓶颈,需从‌索引优化‌、‌查询逻辑调整‌、‌服务器配置调优‌、‌架构扩展‌等多维度综合解决,具体策略如下: 一、索引优化 补充缺失索引‌ 通过慢查询日志定位高频低效 SQL,使用 EXPLAIN 分…...

【MySQL】MySQL 表的增删改查(CRUD)—— 下篇(内含聚合查询、group by和having子句、联合查询、插入查询结果)

目录 1. 插入查询结果 2 聚合查询 (行与行之间运算) count 计算查询结果的行数 sum 求和 avg 求平均值 max 最大值 min 最小值 【小结】 3. group by 子句 分组 where 条件 having 条件 4. 联合查询(多表查询) 内连接…...

简化K8S部署流程:通过Apisix实现蓝绿发布策略详解(上)

本次主题主要目的是为大家讲解蓝绿发布,但是发现文档和内容太长了,对此将文档拆分成了两部分,视频拆分成了好几部分,这样大家刷起来没疲劳感。 第一部分《apisix argorollout 实现蓝绿发布I-使用apisix发布应用》,主要…...

FLV 与 MP4 格式深度剖析:结构、原理

1 FLV格式分析 1.1 定义 FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式,由于其封装后的⾳视频⽂件体积⼩、封装简单等特点,⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持FLV。采⽤FLV格式封装的⽂件后缀为.flv FLV封装格式是由⼀个**⽂件…...

k8s的yaml文件里的volume跟volumeMount的区别

volume 是 Pod 级别的资源,用于定义存储卷。它是一个独立于容器的存储资源,可以被一个或多个容器共享使用。volume 的定义位于 Pod 的 spec.volumes 部分。 特点 独立性:volume 是 Pod 的一部分,而不是容器的一部分。它独立于容…...

Git常用操作命令

配置 Git git config --global user.name "Your Name": 设置用户名。git config --global user.email "your_emailexample.com": 设置用户邮箱。 初始化和克隆仓库 git init: 初始化一个新的 Git 仓库。git clone [URL]: 克隆一个远程仓库到本地。 git cl…...

09.传输层协议 ——— TCP协议

文章目录 TCP协议 谈谈可靠性TCP协议格式 序号与确认序号窗口大小六个标志位 确认应答机制(ACK)超时重传机制连接管理机制 三次握手四次挥手 流量控制滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP的应用层协议 TCP协…...

NineData 与飞书深度集成,企业级数据管理审批流程全面自动化

NineData 正式推出与飞书审批系统的深度集成功能,企业用户在 NineData 平台发起的审批工单,将自动推送至审批人的飞书中,审批人可以直接在飞书进行审批并通过/拒绝。该功能实现跨系统协作,带来巨大的审批效率提升,为各…...

WebRTC服务器Coturn服务器中的通信协议

1、概述 作为WebRTC服务器,coturn通信协议主要是STUN和TURN协议 STUN&TURN协议头部都是20个字节,用 Message Type来区分不同的协议 |------2------|------2------|------------4------------|------------------------12-------------------------|-----------…...

4.19除自身以外数组的乘积

我自己的思路,想用双指针, 一个从左边left开始乘,一个从右边right开始乘,如果left,或者right遇到了目标索引i(也就是我们要跨过去的当前元素),那么直接让对应的指针加一,当前元素不参与累积的计算&#xff…...

Anaconda3使用conda进行包管理

一、基础包管理操作 ‌安装包‌ 使用 conda install <包名> 安装指定包&#xff0c;支持多包批量安装和版本指定&#xff1a; conda install numpy # 安装单个包 conda install numpy scipy pandas # 批量安装多个包 conda install numpy1.21 # 指定版本 conda instal…...

媒体关注:联易融聚焦AI+业务,重塑供应链金融生态

近日&#xff0c;供应链金融科技龙头企业联易融科技集团&#xff08;以下简称“联易融”&#xff09;发布的公告显示&#xff0c;截至2024年末&#xff0c;公司现金储备达51亿元&#xff0c;同比上一年增加2亿元。公司称&#xff0c;公司经营性现金流保持健康&#xff0c;现金储…...

安装 Conda 环境

安装 Conda 环境&#xff1a;快速指南 什么是 Conda&#xff1f; Conda 是一个开源的跨平台包管理器和环境管理系统&#xff0c;支持 Python、R、Julia 等语言。它广泛用于数据科学和机器学习领域&#xff0c;能够轻松创建、管理和切换开发环境。 安装步骤 1. 安装 Anaconda…...

Qt Creator 创建 Qt Quick Application一些问题

一、Qt Creator 创建 Qt Quick Application 时无法选择 MSVC 编译器(即使已安装 Qt 5.15.2 和 MSVC2019) 1、打开 Qt Creator 的编译器设置 工具 (Tools) → 选项 (Options) → Kits → 编译器 (Compilers) 检查是否存在 Microsoft Visual C++ Compiler (x86_amd64) 或类似条…...

Spark-Streaming核心编程

以下是今天所学的知识点与代码测试&#xff1a; Spark-Streaming DStream实操 案例一&#xff1a;WordCount案例 需求&#xff1a;使用 netcat 工具向 9999 端口不断的发送数据&#xff0c;通过 SparkStreaming 读取端口数据并统计不同单词出现的次数 实验步骤&#xff1a;…...

深度剖析神经网络:从基础原理到面试要点(二)

引言 在人工智能蓬勃发展的今天&#xff0c;神经网络作为其核心技术之一&#xff0c;广泛应用于图像识别、自然语言处理、语音识别等众多领域。深入理解神经网络的数学模型和结构&#xff0c;对于掌握人工智能技术至关重要。本文将对神经网络的关键知识点进行详细解析&#xf…...

c#操作excel

说明 vs2022开发&#xff0c;调用excel 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Sy…...

MQTTX + MCP:MQTT 客户端秒变物联网 Agent

引言&#xff1a;MQTTX 与 MCP 的融合 作为最受欢迎的 MQTT 客户端工具&#xff0c;MQTTX 在 1.12.0 beta 版本中集成了模型上下文协议&#xff08;MCP&#xff09;到 Copilot AI 功能中&#xff0c;显著提升了服务能力。这一融合让 MQTTX 转变为 MCP Host&#xff08;也就是发…...

GSAP 动画引擎实战:打造丝滑动效交互组件库

目录 一、前言二、项目初始化三、核心动效组件实战1. 元素淡入组件&#xff1a;FadeIn.vue2. 列表级联动画&#xff1a;SlideList.vue3. 滚动触发 Reveal 动画&#xff1a;ScrollReveal.vue4. 拖拽盒子组件&#xff1a;DraggableBox.vue5. 打字机效果组件&#xff1a;Typewrite…...

[OpenGL] Lambertian材质漫反射BRDF方程的解释与推导

一、简介 本文简单的介绍了 Physical Based Rendering, PBR 中的 Lambertian 材质漫反射BRDF公式 f r l a m b e r t i a n c d i f f π fr_{lambertian}\frac{c_{diff}}{\pi} frlambertian​πcdiff​​的推导。 二、漫反射项 根据 渲染方程&#xff1a; L o ( v ) ∫ …...

网易云音乐如何修改缓存地址到D盘

你可以通过创建 符号链接&#xff08;Symbolic Link&#xff09; 将网易云音乐的缓存目录转移到D盘&#xff0c;无需修改软件设置。以下是具体步骤&#xff1a; 操作步骤 关闭网易云音乐 确保程序完全退出&#xff08;任务栏右下角无残留进程&#xff09;。 备份并移动原缓存文…...

react使用01

React.cloneElement(element,props,…children) 这个是React的官方API&#xff0c;&#xff0c;主要用于克隆并修改React元素&#xff0c;&#xff0c; 本质&#xff1a; 复制一个已有的React元素&#xff0c;并允许你修改他的props element : 必须是一个有效的element元素p…...

yooAsset打包后材质丢失

以安卓为目标平台打出的AssetBundle包&#xff08;尤其是YooAsset打出的&#xff09;&#xff0c;在Window下Unity编辑器以HostPlayMode运行&#xff0c;有时显示会丢失部分材质。 这是因为安卓目标的AssetBundle包适合OpenglES&#xff0c;而window下Unity编辑器模式是Dx11&a…...

Codeforces Round 1019 (Div. 2)

A. Common Multiple 找不同的数字 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() {int t; cin >> t;while (t--) {int n;cin >> n;vector<int> a(n);for (int i 0; i < n; i)cin >&…...

【Spring Boot】MyBatis多表查询的操作:注解和XML实现SQL语句

1.准备工作 1.1创建数据库 &#xff08;1&#xff09;创建数据库&#xff1a; CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;&#xff08;2&#xff09;使用数据库 -- 使⽤数据数据 USE mybatis_test;1.2 创建用户表和实体类 创建用户表 -- 创建表[⽤⼾表…...

Docker离线安装与配置指南

Docker离线安装与配置指南 离线安装步骤 1. 下载离线安装包 官方下载地址&#xff1a; https://download.docker.com/linux/static/stable/x86_64/注意&#xff1a;国内用户若无法访问&#xff0c;可能需要使用科学上网工具。本文档以Docker 20.10.23版本为例。 2. 安装与部…...

N8N 官方 MCP 节点实战指南:AI 驱动下的多工具协同应用场景全解析

在低代码自动化领域&#xff0c;N8N 凭借其强大的节点扩展能力和灵活的工作流编排&#xff0c;成为企业构建复杂自动化流程的首选工具。随着 AI Agent 技术的兴起&#xff0c;通过 MCP&#xff08;Multi-Tool Coordination Protocol&#xff09;实现 AI 与外部工具的协同调用&a…...

v-html 显示富文本内容

返回数据格式&#xff1a; 只有图片名称 显示不出完整路径 解决方法&#xff1a;在接收数据后手动给img格式的拼接vite.config中的服务器地址 页面&#xff1a; <el-button click"">获取信息<el-button><!-- 弹出层 --> <el-dialog v-model&…...

UWB与GPS技术融合的室内外无缝定位方案

‌ 一、技术原理与互补性‌ ‌双模定位机制‌ ‌室外场景‌&#xff1a;GPS/北斗提供‌10-30厘米级定位精度‌&#xff08;RTK技术辅助&#xff09;&#xff0c;覆盖露天区域。‌室内场景‌&#xff1a;UWB通过‌TOF/TDOA算法‌实现‌10-50厘米级定位精度‌&#xff0c;穿透金…...

AiEditor v1.3.8 发布

2025 年 4 月 22 日&#xff0c;AI 富文本编辑器 AiEditor 发布了 v1.3.8 版本。 AiEditor 是一个面向 AI 的下一代富文本编辑器&#xff0c;基于 Web Component 开发&#xff0c;支持 Layui、Vue、React、Angular 等几乎任何前端框架&#xff0c;适配 PC Web 端和手机端&#…...