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

从ChatGLM2-6B来看大模型扩展上下文和加速推理相关技术

       ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上,ChatGLM2-6B 引入了如下新特性:

  1. 更强大的性能:基于 ChatGLM 初代模型的开发经验,全面升级了 ChatGLM2-6B 的基座模型。ChatGLM2-6B 使用了 GLM 的混合目标函数,经过了 1.4T 中英标识符的预训练与人类偏好对齐训练,评测结果显示,相比于初代模型,ChatGLM2-6B 在 MMLU(+23%)、CEval(+33%)、GSM8K(+571%) 、BBH(+60%)等数据集上的性能取得了大幅度的提升,在同尺寸开源模型中具有较强的竞争力。

  2. 更长的上下文:基于 FlashAttention 技术,将基座模型的上下文长度(Context Length)由 ChatGLM-6B 的 2K 扩展到了 32K,并在对话阶段使用 8K 的上下文长度训练。对于更长的上下文,发布了 ChatGLM2-6B-32K 模型。LongBench 的测评结果表明,在等量级的开源模型中,ChatGLM2-6B-32K 有着较为明显的竞争优势。

  3. 更高效的推理:基于 Multi-Query Attention 技术,ChatGLM2-6B 有更高效的推理速度和更低的显存占用:在官方的模型实现下,推理速度相比初代提升了 42%,INT4 量化下,6G 显存支持的对话长度由 1K 提升到了 8K。

  4. 更开放的协议:ChatGLM2-6B 权重对学术研究完全开放,在填写问卷进行登记后亦允许免费商业使用。

一、ChatGLM2-6B评测结果

       下面是ChatGLM2-6B 模型在 MMLU (英文)、C-Eval(中文)、GSM8K(数学)、BBH(英文) 上的测评结果。在 evaluation 中提供了在 C-Eval 上进行测评的脚本。

MMLU

ModelAverageSTEMSocial SciencesHumanitiesOthers
ChatGLM-6B40.6333.8944.8439.0245.71
ChatGLM2-6B (base)47.8641.2054.4443.6654.46
ChatGLM2-6B45.4640.0651.6141.2351.24
ChatGLM2-12B (base)56.1848.1865.1352.5860.93
ChatGLM2-12B52.1347.0061.0046.1056.05

Chat 模型使用 zero-shot CoT (Chain-of-Thought) 的方法测试,Base 模型使用 few-shot answer-only 的方法测试

C-Eval

ModelAverageSTEMSocial SciencesHumanitiesOthers
ChatGLM-6B38.933.348.341.338.0
ChatGLM2-6B (base)51.748.660.551.349.8
ChatGLM2-6B50.146.460.450.646.9
ChatGLM2-12B (base)61.655.473.764.259.4
ChatGLM2-12B57.052.169.358.553.2

Chat 模型使用 zero-shot CoT 的方法测试,Base 模型使用 few-shot answer only 的方法测试

GSM8K

ModelAccuracyAccuracy (Chinese)*
ChatGLM-6B4.825.85
ChatGLM2-6B (base)32.3728.95
ChatGLM2-6B28.0520.45
ChatGLM2-12B (base)40.9442.71
ChatGLM2-12B38.1323.43

所有模型均使用 few-shot CoT 的方法测试,CoT prompt 来自 http://arxiv.org/abs/2201.11903

使用翻译 API 翻译了 GSM8K 中的 500 道题目和 CoT prompt 并进行了人工校对

BBH

ModelAccuracy
ChatGLM-6B18.73
ChatGLM2-6B (base)33.68
ChatGLM2-6B30.00
ChatGLM2-12B (base)36.02
ChatGLM2-12B39.98

所有模型均使用 few-shot CoT 的方法测试,CoT prompt 来自 https://github.com/suzgunmirac/BIG-Bench-Hard/tree/main/cot-prompts

二、推理性能

       ChatGLM2-6B 使用了 Multi-Query Attention,提高了生成速度。生成 2000 个字符的平均速度对比如下

Model推理速度 (字符/秒)
ChatGLM-6B31.49
ChatGLM2-6B44.62

使用官方实现,batch size = 1,max length = 2048,bf16 精度,测试硬件为 A100-SXM4-80G,软件环境为 PyTorch 2.0.1

        Multi-Query Attention 同时也降低了生成过程中 KV Cache 的显存占用,此外,ChatGLM2-6B 采用 Causal Mask 进行对话训练,连续对话时可复用前面轮次的 KV Cache,进一步优化了显存占用。因此,使用 6GB 显存的显卡进行 INT4 量化的推理时,初代的 ChatGLM-6B 模型最多能够生成 1119 个字符就会提示显存耗尽,而 ChatGLM2-6B 能够生成至少 8192 个字符。

量化等级编码 2048 长度的最小显存生成 8192 长度的最小显存
FP16 / BF1613.1 GB12.8 GB
INT88.2 GB8.1 GB
INT45.5 GB5.1 GB

ChatGLM2-6B 利用了 PyTorch 2.0 引入的 torch.nn.functional.scaled_dot_product_attention 实现高效的 Attention 计算,如果 PyTorch 版本较低则会 fallback 到朴素的 Attention 实现,出现显存占用高于上表的情况。

        量化对模型性能的影响如下,基本在可接受范围内。

量化等级Accuracy (MMLU)Accuracy (C-Eval dev)
BF1645.4753.57
INT443.1350.30

三、Multi-Query-Attention(MQA)

论文地址:https://arxiv.org/pdf/1911.02150.pdf

       MQA 是 19 年提出的一种新的 Attention 机制,其能够在保证模型效果的同时加快 decoder 生成 token 的速度,因此在目前大模型时代被广泛应用。下面看一下论文的实验效果:

        从上图表中可以看到,MQA 在 encoder 上的提速没有非常明显,但在 decoder 上的提速是很显著的。

      传统的Transformer是Multi Head Attention(MHA)结构,每个 head 又是由: query(Q),key(K),value(V) 3 个矩阵共同实现的,这三个矩阵的参数都是独立的,而MQA 让所有的头之间 共享 同一份 Key 和 Value 矩阵,每个头只单独保留了一份 Query 参数,从而大大减少 Key 和 Value 矩阵的参数量

       他们的关键区别在于Wqkv的实现上,下面展示一下代码示例:

# Multi Head Attentionself.Wqkv = nn.Linear(                        # 【关键】Multi-Head Attention 的创建方法    self.d_model,     3 * self.d_model,                         # 有 query, key, value 3 个矩阵, 所以是 3 * d_model    device=device)query, key, value = qkv.chunk(                # 【关键】每个 tensor 都是 (1, 512, 768)    3,     dim=2)# Multi Query Attentionself.Wqkv = nn.Linear(                                # 【关键】Multi-Query Attention 的创建方法    d_model,    d_model + 2 * self.head_dim,                      # 只创建 query 的 head 向量,所以只有 1 个 d_model    device=device,                                    # 而 key 和 value 不再具备单独的头向量)query, key, value = qkv.split(                        # query -> (1, 512, 768)    [self.d_model, self.head_dim, self.head_dim],     # key   -> (1, 512, 96)    dim=2                                             # value -> (1, 512, 96))

        在 MHA 中,query, key, value 每个向量均有 768 维度;而在 MQA 中,只有 query 是 768 维,而 key 和 value 只有 96 维,恰好是 1 个 head_dim 的维度。除了 query 向量还保存着 8 个头,key 和 value 向量都只剩 1 个「公共头」了

下面来测试一下MHA和MQA维度的变化:

import mathimport warningsimport torchimport torch.nn as nnfrom einops import rearrangefrom typing import Optionaldef scaled_multihead_dot_product_attention(        query,        key,        value,        n_heads,        past_key_value=None,        softmax_scale=None,        attn_bias=None,        key_padding_mask=None,        is_causal=False,        dropout_p=0.0,        training=False,        needs_weights=False,        multiquery=False,    ):    q = rearrange(query, 'b s (h d) -> b h s d', h=n_heads)         # (1, 512, 768) -> (1, 8, 512, 96)    kv_n_heads = 1 if multiquery else n_heads    k = rearrange(key, 'b s (h d) -> b h d s', h=kv_n_heads)        # (1, 512, 768) -> (1, 8, 96, 512) if not multiquery                                                                     # (1, 512, 96) -> (1, 1, 96, 512)  if multiquery    v = rearrange(value, 'b s (h d) -> b h s d', h=kv_n_heads)      # (1, 512, 768) -> (1, 8, 512, 96) if not multiquery                                                                     # (1, 512, 96) -> (1, 1, 512, 96)  if multiquery        attn_weight = q.matmul(k) * softmax_scale                       # (1, 8, 512, 512)    attn_weight = torch.softmax(attn_weight, dim=-1)                # (1, 8, 512, 512)    out = attn_weight.matmul(v)                                     # (1, 8, 512, 512) * (1, 1, 512, 96) = (1, 8, 512, 96)    out = rearrange(out, 'b h s d -> b s (h d)')                    # (1, 512, 768)    return out, attn_weight, past_key_valueclass MultiheadAttention(nn.Module):    """Multi-head self attention.    Using torch or triton attention implemetation enables user to also use    additive bias.    """    def __init__(        self,        d_model: int,        n_heads: int,        attn_impl: str = 'triton',        clip_qkv: Optional[float] = None,        qk_ln: bool = False,        softmax_scale: Optional[float] = None,        attn_pdrop: float = 0.0,        low_precision_layernorm: bool = False,        verbose: int = 0,        device: Optional[str] = None,    ):        super().__init__()        self.attn_impl = attn_impl        self.clip_qkv = clip_qkv        self.qk_ln = qk_ln        self.d_model = d_model        self.n_heads = n_heads        self.softmax_scale = softmax_scale        if self.softmax_scale is None:            self.softmax_scale = 1 / math.sqrt(self.d_model / self.n_heads)        self.attn_dropout_p = attn_pdrop        self.Wqkv = nn.Linear(self.d_model, 3 * self.d_model, device=device)        fuse_splits = (d_model, 2 * d_model)        self.Wqkv._fused = (0, fuse_splits)  # type: ignore        self.attn_fn = scaled_multihead_dot_product_attention        self.out_proj = nn.Linear(self.d_model, self.d_model, device=device)        self.out_proj._is_residual = True  # type: ignore    def forward(        self,        x,        past_key_value=None,        attn_bias=None,        attention_mask=None,        is_causal=True,        needs_weights=False,    ):        qkv = self.Wqkv(x)                                              # (1, 512, 2304)        if self.clip_qkv:            qkv.clamp_(min=-self.clip_qkv, max=self.clip_qkv)        query, key, value = qkv.chunk(3, dim=2)                         # both q, k, v: (1, 512, 768)        key_padding_mask = attention_mask        context, attn_weights, past_key_value = self.attn_fn(            query,            key,            value,            self.n_heads,            past_key_value=past_key_value,            softmax_scale=self.softmax_scale,            attn_bias=attn_bias,            key_padding_mask=key_padding_mask,            is_causal=is_causal,            dropout_p=self.attn_dropout_p,            training=self.training,            needs_weights=needs_weights,        )        return self.out_proj(context), attn_weights, past_key_valueclass MultiQueryAttention(nn.Module):    """Multi-Query self attention.    Using torch or triton attention implemetation enables user to also use    additive bias.    """    def __init__(        self,        d_model: int,        n_heads: int,        attn_impl: str = 'triton',        clip_qkv: Optional[float] = None,        qk_ln: bool = False,        softmax_scale: Optional[float] = None,        attn_pdrop: float = 0.0,        low_precision_layernorm: bool = False,        verbose: int = 0,        device: Optional[str] = None,    ):        super().__init__()        self.attn_impl = attn_impl        self.clip_qkv = clip_qkv        self.qk_ln = qk_ln        self.d_model = d_model        self.n_heads = n_heads        self.head_dim = d_model // n_heads        self.softmax_scale = softmax_scale        if self.softmax_scale is None:            self.softmax_scale = 1 / math.sqrt(self.head_dim)        self.attn_dropout_p = attn_pdrop        self.Wqkv = nn.Linear(            d_model,            d_model + 2 * self.head_dim,            device=device,        )        fuse_splits = (d_model, d_model + self.head_dim)        self.Wqkv._fused = (0, fuse_splits)  # type: ignore        self.attn_fn = scaled_multihead_dot_product_attention        self.out_proj = nn.Linear(self.d_model, self.d_model, device=device)        self.out_proj._is_residual = True  # type: ignore    def forward(        self,        x,        past_key_value=None,        attn_bias=None,        attention_mask=None,        is_causal=True,        needs_weights=False,    ):        qkv = self.Wqkv(x)                                      # (1, 512, 960)        if self.clip_qkv:            qkv.clamp_(min=-self.clip_qkv, max=self.clip_qkv)        query, key, value = qkv.split(                                  # query -> (1, 512, 768)            [self.d_model, self.head_dim, self.head_dim],               # key   -> (1, 512, 96)            dim=2                                                       # value -> (1, 512, 96)        )        key_padding_mask = attention_mask        if self.qk_ln:            # Applying layernorm to qk            dtype = query.dtype            query = self.q_ln(query).to(dtype)            key = self.k_ln(key).to(dtype)        context, attn_weights, past_key_value = self.attn_fn(            query,            key,            value,            self.n_heads,            past_key_value=past_key_value,            softmax_scale=self.softmax_scale,            attn_bias=attn_bias,            key_padding_mask=key_padding_mask,            is_causal=is_causal,            dropout_p=self.attn_dropout_p,            training=self.training,            needs_weights=needs_weights,            multiquery=True,        )        return self.out_proj(context), attn_weights, past_key_value    if __name__ == '__main__':    # attn = MultiQueryAttention(    #     768,    #     8,    #     'torch'    # )    attn = MultiheadAttention(        768,        8,        'torch'    )    attn(        torch.ones(size=(1, 512, 768))    )

四、FlashAttention

论文地址:https://arxiv.org/abs/2205.14135

代码地址:https://github.com/HazyResearch/flash-attention

       Transformer的自注意力机制(self-attention)的计算的时间复杂度和空间复杂度都与序列长度有关,时间复杂度是O(n^2),所以在处理长序列的时候会变的更慢,同时内存会增长更多。通常的优化是针对计算复杂度(通过F L O P s FLOPsFLOPs 数衡量), 优化会权衡模型质量和计算速度。

       在FlashAttention中考虑到attention算法也是IO敏感的,通过对GPU显存访问的改进来对attention算法的实现进行优化。如下图,在GPU中片上存储SRAM访问速度最快,对应的HBM(high bandwidth memory)访问速度较慢,为了加速要尽量减少HBM的访问次数。

4.1 标准Transformer简述

标准的attention算法实现中的QKV都是与HBM交互的,具体如下:

4.2 FlashAttention算法实现的关键三点:

  1. softmax的tiling展开,可以支持softmax的拆分并行计算,从而提升计算效率

  2. 反向过程中的重计算,减少大量的显存占用,节省显存开销。

  3. ​通过CUDA编程实现fusion kernel

4.2.1 softmax展开(tiling)

  •  基本softmax:在计算x_i的值的时候需要用到所有的X=\{x_1,...x_N\}值,计算公式如下:

  • 安全(safe) softmax:由于e^{x_i} 很容易溢出, 比如FP16支持范围是2^-24\sim65504,当x_i>11 的时候,  e^{x_i}会超过float16的有效位。为解决这个问题提出 safe softmax, 对每个x_i  都减去一个m=max^N_{j=1}(x_j)  , 使得x_i-m\ll0  , 这时幂操作符对负数输入的计算是准确且安全的。

  • Safe softmax tiling:对于 X 分为两组情况进行说明,其中X=[X^{(1)},X^{(2)}]  

  • safe softmax基本计算示例

  • safe softmax tiling计算示例(结果跟基本计算示例一致)

      有了softmax tiling的基础以后,在执行的时候可以对Q、K、V 三个矩阵进行分块操作并行计算了,如下图所示:

4.2.2 反向过程中的重计算

        类似于gradient checkpoint方法,在前向的时候把输出结果O=softmax(QK^T)V  、 l 、 m 存入HBM中, 在反向时候重新计算需要的数据,最终完整的算法说明如下:

4.3 实验效果

BERT

GPT-2

 Long-range Arena

参考文献

[1] https://github.com/THUDM/ChatGLM2-6B

[2] https://link.zhihu.com/?target=https%3A//github.com/mosaicml/llm-foundry/blob/9c89ab263e72fb9610f28c8ab9cde5d2205b6bff/llmfoundry/models/layers/attention.py

[3]https://paperswithcode.com/paper/flashattention-fast-and-memory-efficient

相关文章:

从ChatGLM2-6B来看大模型扩展上下文和加速推理相关技术

ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上,ChatGLM2-6B 引入了如下新特性: 更强大的性能:基于 ChatGLM 初代模型的开发经验,全面…...

Unity特效总览

一、粒子 Unity中的粒子组件叫做Particle System。 粒子系统顾名思义,与“微粒”有关。粒子系统会生成和发射很多粒子,通过控制粒子的生成数量、大小、角度、速度、贴图和颜色等众多属性,可以实现或真实或炫酷的各种效果。其中,…...

Unity中人物控制器

在Unity中控制器是很常见的功能,一般的人物控制器有两种方法,一种是通过代码实现,另外一种就是通过Unity中的API实现。   这里主要介绍第一种方法。 首先对控制器步骤进行分析。 步骤1:通过方向键控制人物移动。 步骤2&#xff…...

零钱兑换-输出组合数

1.暴力递归 &#xff08;1&#xff09;剩余金额小于0&#xff0c;无解 剩余金额等于0&#xff0c;有解 剩余金额大于0&#xff0c;继续递归 &#xff08;2&#xff09;从大的硬币到小的硬币&#xff0c;可以减少循环次数 #include <bits/stdc.h> using namespace std;…...

Mybatis 小结

一、Mybatis 基本构成 MyBatis的整体分为基础支持层、核心处理层、接口。 1.1、基础支持层 1.1.1、数据源模块 MyBatis自身提供了相应的数据源实现&#xff0c;也提供了与第三方接口数据源集成的接口&#xff0c;这些功能都位于数据源模块之中。 1.1.2、事务管理模块 …...

【Cartopy】库的安装和瓦片加载(天地图、高德等)

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 Cartopy基础入门 【Cartopy】库的安装和天地图瓦片加载 【Cartopy】【Cartopy】如何更好的确定边界显示 【Cartopy】【Cartopy】如何丝滑的加载Geojso…...

TCPDF生成PDF文件,含jpjraph生成雷达图

TCPDF生成PDF文件&#xff0c;含jpjraph生成雷达图 依赖自行安装 "tecnickcom/tcpdf": "^6.6","amenadiel/jpgraph": "4"雷达图生成 中文字体添加安装 没有封装&#xff0c;只作为测试案例展示 // 创建新的PDF文档$pdf new \TCPD…...

Flink-串讲面试题

1. 概念 有状态的流式计算框架 可以处理源源不断的实时数据&#xff0c;数据以event为单位&#xff0c;就是一条数据。 2. 开发流程 先获取执行环境env&#xff0c;然后添加source数据源&#xff0c;转换成datastream&#xff0c;然后使用各种算子进行计算&#xff0c;使用s…...

如何培养对技术的热爱

这篇博文主要针对计算机专业相关的同学&#xff0c;对于理工科专业的同学有一定的借鉴意义&#xff0c;对于其他专业的同学&#xff0c;还请自行取舍。 背景 初学计算机&#xff0c;可能并不是每个人都能对其产生兴趣&#xff0c;更不要说从其中获得快乐。对于如何培养兴趣&a…...

Vue响应式数据的原理

在 vue2 的响应式中&#xff0c;存在着添加属性、删除属性、以及通过下标修改数组&#xff0c;但页面不会自动更新的问题。而这些问题在 vue3 中都得以解决。 vue3 采用了 proxy 代理&#xff0c;用于拦截对象中任意属性的变化&#xff0c;包括&#xff1a;属性的读写、属性的…...

pytest fixture 用于teardown工作

fixture通过scope参数控制setup级别&#xff0c;setup作为用例之前前的操作&#xff0c;用例执行完之后那肯定也有teardown操作。这里用到fixture的teardown操作并不是独立的函数&#xff0c;用yield关键字呼唤teardown操作。 举个例子&#xff1a; 输出&#xff1a; 说明&…...

39 printf 的输出到设备层的调试

前言 在前面 printf 的调试 我们只是调试到了 glibc 调用系统调用, 封装了参数 stdout, 带输出的字符缓冲, 以及待输出字符长度 然后内核这边 只是到了 write 的系统调用, 并未向下细看 我们这里 稍微向下 细追一下, 看看 到达设备层面 这里是怎么具体的 impl 的 测试用例…...

数字普惠金融、数字创新与经济增长—基于省级面板数据的实证考察(2011-2021年)

参照陈啸&#xff08;2023&#xff09;的做法&#xff0c;本对来自经济问题《数字普惠金融、数字创新与经济增长——基于省级面板数据的实证考察》一文中的基准回归部分进行复刻。数字普惠金融、数字创新已经成为驱动经济高质量发展的关键。利用省级面板数据&#xff0c;构建固…...

控制renderQueue解决NGUI与Unity3D物体渲染顺序问题

NGUI与Unity3D物体渲染顺序问题&#xff0c;做过UI的各位应该都遇到过。主要指的是UI与Unity制作的特效、3D人物等一同显示时的层次问题。 由于UI与特效等都是以transparent方式渲染&#xff0c;而Unity与NGUI在管理同是透明物体的render queue时实际上互相没有感知&#xff0…...

概率论与数理统计:第二、三章:一维~n维随机变量及其分布

文章目录 Ch2. 一维随机变量及其分布1.一维随机变量1.随机变量2.分布函数 F ( x ) F(x) F(x)(1)定义(2)分布函数的性质 (充要条件)(3)分布函数的应用——求概率3.最大最小值函数 2.一维离散型随机变量及其概率分布(分布律)3.一维连续型随机变量及其概率分布(概率密度)4.一般类型…...

BOLT- 识别和优化热门的基本块

在BOLT中&#xff0c;识别和优化热门的基本块之所以关键&#xff0c;是因为BOLT的主要目标是优化程序以更好地利用硬件特性&#xff0c;特别是指令缓存&#xff08;ICache&#xff09;。以下是BOLT如何识别和优化热门基本块的流程&#xff1a; 收集性能数据: BOLT开始的时候并不…...

Golang 中的 time 包详解(四):函数详解

在日常开发过程中&#xff0c;会频繁遇到对时间进行操作的场景&#xff0c;使用 Golang 中的 time 包可以很方便地实现对时间的相关操作。接下来的几篇文章会详细讲解 time 包&#xff0c;本文讲解一下 time 包中的函数。 func Now() Time 返回当前的系统时间。 package mai…...

【前端 | CSS】5种经典布局

页面布局是样式开发的第一步&#xff0c;也是 CSS 最重要的功能之一。 常用的页面布局&#xff0c;其实就那么几个。下面我会介绍5个经典布局&#xff0c;只要掌握了它们&#xff0c;就能应对绝大多数常规页面。 这几个布局都是自适应的&#xff0c;自动适配桌面设备和移动设备…...

腾讯云宣布VPC网络架构重磅升级,可毫秒级感知网络故障并实现自愈

8月11日&#xff0c;腾讯云宣布VPC&#xff08;Virtual Private Cloud&#xff0c;云私有网络&#xff09;架构重磅升级。新架构采用多项腾讯核心自研技术&#xff0c;能够支撑用户构建业界最大 300万节点超大规模单VPC网络&#xff0c;并将转发性能最大提升至业界领先的200Gbp…...

vue 路由页面跳转

从index.vue跳转到data.vue index.vue <el-table-column label"客户数" align"center" :show-overflow-tooltip"true"><template slot-scope"scope"><router-link :to"/system/enterprise-data/index/ scope.ro…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...