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

产品化Chatgpt所面临的五大技术挑战

2022年11月,ChatGPT横扫全球,成为应用人工智能(AI)领域迄今为止最令人惊叹的“哇!”时刻,也是当前科技投资激增的催化剂。2023年11月,首席执行官Sam Altman宣布该产品周用户量达到1亿,这在该领域内的增长速度是前所未有的。随着用户量爆炸性增长,真正的扩展挑战是什么呢?为了深入了解,我再次采访了Evan Morikawa,他是ChatGPT发布和扩展过程中的应用工程团队负责人。那么,让我们听听Evan的分享。

1. 关于OpenAI和Evan的简介


Evan是如何加入OpenAI,并最终领导应用工程团队的?这个团队也参与了ChatGPT的构建。

OpenAI是ChatGPT的创造者,ChatGPT只是公司众多产品之一。其他产品包括DALL·E 3(图像生成)、GPT-4(一种高级模型)以及OpenAI API,开发者和公司利用这个API将AI整合到他们的流程中。ChatGPT和API都提供了多种模型类别:GPT-3、GPT-3.5和GPT-4。

负责制作和扩展这些产品的工程、产品和设计组织称为“应用”,成立于2020年GPT-3发布时。它的主要任务是安全地将OpenAI的研究成果推向世界。OpenAI本身成立于2015年,今天公司的核心仍然是一个研究实验室,旨在创建一个安全且对齐的人工通用智能(AGI)。

2. ChatGPT是如何工作的?回顾一下。

对于那些没有从头开始构建ChatGPT的人来说,它是如何工作的?

为了引入一些扩展话题,让我简单介绍一下这些AI模型是如何工作的。如果你已经熟悉基础知识,可以跳到第3部分。

当你向ChatGPT提问时,会发生几个步骤:

输入。我们从文本输入中获取你的文本。

分词。我们将其切分成令牌。一个令牌大致对应几个Unicode字符。你可以将其视为一个词。

创建嵌入向量。我们将每个令牌转换成一系列数字,这被称为嵌入向量。

通过模型权重乘以嵌入向量。然后,我们将这些嵌入向量与数以百亿计的模型权重相乘。

抽样预测。在这些乘法操作结束时,数字向量代表了下一个最可能令牌的概率。接下来最可能的令牌是从ChatGPT中输出的下几个字符。

让我们可视化这些步骤。前两步比较简单:

步骤1和2:当你向ChatGPT提出问题时发生的事情
注意,分词不一定意味着将文本分成单词;令牌也可以是单词的子集。

嵌入向量是大型语言模型(LLM)的核心,我们在下一步从令牌中创建它们:

步骤3:当你向ChatGPT提出问题时发生的事情。嵌入向量代表了令牌作为向量。上述嵌入向量中的值是示例
一个嵌入向量是令牌的多维表示。我们明确训练一些模型,以显式允许捕获单词或短语之间的语义意义和关系。例如,“狗”和“小狗”的嵌入向量在几个维度上比“狗”和“电脑”更接近。这些多维嵌入向量帮助机器更有效地理解人类语言。

模型权重用于计算加权嵌入向量矩阵,这用于预测下一个可能的令牌。对于这一步,我们需要使用OpenAI的权重矩阵,该矩阵由数以百亿计的权重组成,并将其与我们从嵌入向量构造的矩阵相乘。这是一次计算密集型的乘法操作。

步骤4:当你向ChatGPT提出问题时发生的事情。权重矩阵包含数以百亿计的模型权重抽样预测是在我们进行了数十亿次乘法操作后完成的。最终向量代表了下一个最可能令牌的概率。抽样是我们选择下一个最可能的令牌并将其发送给用户的过程。ChatGPT中的每个单词都是通过每秒多次重复这个过程生成的。

预训练和推理
我们如何生成这套复杂的模型权重,其值编码了大部分人类知识?我们通过一个称为预训练的过程来完成。预训练的目标是构建一个模型,它可以预测下一个令牌(你可以将其视为一个词),对于互联网上的所有单词都是如此。

在预训练期间,通过梯度下降,权重会逐渐更新,这是一种数学优化方法。梯度下降的类比是一位徒步旅行者被困在山上,他们正试图下山。然而,由于浓雾限制了他们的视野,他们只能看到周围的一小片区域。梯度下降意味着查看徒步旅行者当前位置的坡度,并朝着最陡峭的下降方向前进。我们可以假设从简单的观察中并不明显坡度,但幸运的是,这位徒步旅行者有一个测量坡度的仪器。然而,进行单次测量需要时间,他们希望在日落前下山。因此,这位徒步旅行者需要决定多久停下来测量一次坡度,以便他们还能在日落前下山。

一旦我们有了我们的模型,我们就可以在其上运行推理,这是当我们用文本提示模型时发生的事情。例如,提示可能是:“为Pragmatic Engineer写一篇客座文章。”这个提示然后要求模型预测下一个最可能的令牌(单词)。它基于过去的输入做出这个预测,并且这个过程反复进行,一个接一个地令牌,一个接一个地单词,直到它吐出你的帖子!

自我关注的可扩展性挑战

在底层,我们使用的是Transformer架构,其关键特性是每个令牌都知道每个其他令牌。这种方法被称为自我关注。一个后果是,你的文本越长——或上下文越多——需要的数学运算就越多。

不幸的是,自我关注的规模呈二次方增长。如果你想让模型预测第100个令牌,它需要做大约10,000次操作。如果你想让它预测第1,000个令牌,它需要做大约1,000,000次操作。

起初,这听起来像是坏消息。然而,我们可以使用一些巧妙的方法来规避这个二次方规模问题。在我们讨论如何解决它之前,我们需要讨论为ChatGPT提供动力的基础设施。

3. GPU的重要性

GPU(图形处理单元)是ChatGPT及其构建的API的生命线。GPU的极度短缺、它们的怪癖和成本主导了我们的运营和扩展方式。

为了铺垫,让我介绍一下我们使用的一种GPU。
NVIDIA H100。NVIDIA H100。它配备了特殊的高带宽内存(HBM),每个GPU都附加了HBM内存。GPU之间可以通过一种高带宽互连叫做NVLink进行通信,它们可以通过一种特殊的以太网替代品叫做Infiniband与外界通信。我们在单个节点中打包了8个这样的GPU。Nvidia销售了一种类似的配置,称为DGX H100。对我们来说,每一点增加的计算或带宽直接影响ChatGPT用户体验。

4. 五大扩展挑战


有很多关于GPU的扩展挑战需要讨论。我们关注的是:

#1:GPU RAM和KV缓存

#2:批量大小、操作:字节比和算术强度

#3:衡量正确指标的重要性

#4:在任何地方寻找GPU

#5:缺乏自动扩展

在我们扩展ChatGPT时,理解这些是至关重要的。让我们深入了解!

挑战#1:KV缓存和GPU RAM
我们的一个大挑战是自我关注的规模呈二次方增长,这意味着我们生成的令牌越多,我们需要的操作就越多(大约对于第100个令牌是~10,000次操作,但对于第1,000个令牌是大约1,000,000次)。我们如何提高性能?

一个初始的解决方法是缓存我们为所有先前令牌所做的数学运算;即KV缓存。我们在我们的机器学习(ML)模型中使用注意力机制。有了这个模型,我们使用三个向量:

Q:与我们包含的内容相关

K:与我们用作输入到输出的内容相关

V:学到的向量;计算的输出

我们可以缓存K和V,因此得名“KV缓存”。然而,我们不能缓存Q,因为这个向量每次都会改变。

我们必须将KV缓存存储在GPU RAM中。这是因为在GPU RAM中移动数据的速度大约为3TB/秒,当我们使用高带宽内存(HBM)时。然而,如果我们将数据通过PCIe总线(PCI Express:一种高速总线标准,常见于主板上用于数据传输)推送,我们得到的速度大约为30GB/秒。使用HBM的速度大约快两个数量级(大约100倍)!

为什么HBM这么快?它是通过堆叠层与GPU物理绑定的,拥有数千个引脚,用于大规模并行数据吞吐量。

这种GPU HBM RAM非常昂贵且相当有限。大多数HBM RAM也用于保存模型权重。就像任何缓存一样,当它填满时,我们通过“过期”最旧的数据来释放空间。

“缓存未命中”对我们的用例来说非常昂贵。缓存未命中是指系统尝试从缓存中检索数据——比如KV缓存——但没有缓存任何内容的事件。通常是因为我们不得不“过期”这个值,并将其从我们的HBM内存中踢出来以释放空间。如果发生缓存未命中,我们需要重新计算整个ChatGPT对话!而且我们处于第1,000个字符,所以那可能更接近1,000,000次操作!

我们的基础设施在用户之间共享GPU RAM。这意味着作为用户,如果你的对话闲置时间过长,你的对话可能会从系统(GPU缓存)中被逐出,因为我们需要为其他对话释放空间。

这种缓存方法有几个含义:

GPU RAM是最宝贵的商品。实际上,GPU RAM而不是计算资源,是LLM操作最常见的瓶颈。

缓存未命中率非常重要!缓存未命中是指系统尝试从缓存中检索数据——如KV缓存——但没有缓存任何内容的事件。缓存未命中对GPU工作量的影响是巨大的,非线性的。缓存未命中率越高,GPU需要做的工作就越多,呈二次方而非线性。

这意味着在扩展ChatGPT时,没有一些简单的CPU利用率指标可以查看。我们不得不关注KV缓存利用率,以及如何最大化GPU RAM。

挑战#2:优化批量大小
批量大小是扩展ChatGPT时需要平衡的第二个指标。粗略地说,批量大小是我们通过GPU运行的并发请求的数量。H100 GPU最多可以在一秒钟内将3.35TB的RAM移动到其寄存器中。GPU寄存器是快速的片上内存,存储计算核心将要执行的操作数。在数据移动到寄存器的同一秒钟内,H100可以乘以1.98千万亿个8位浮点数。让我们将这1.98千万亿次操作除以移动的3.35TB数据;H100可以在移动1字节所需的时间内执行591次浮点运算。H100的操作:字节比为591:1。如果你要花时间移动1GB,你应该至少每秒执行591亿次浮点运算(FLOPS)。如果做得少于这个数值,意味着浪费了GPU FLOPS。然而,如果你做得更多,你就在等待内存带宽。在我们的模型中,我们移动的内存量相对固定,大约是我们模型权重的大小。通过调整我们的批量大小,我们对这个过程有一定的控制,这改变了涉及的数学计算量。

在扩展ChatGPT时,我们需要充分“饱和”GPU,这意味着监控我们的批量大小,以便我们有正确的FLOPS,这样GPU就不会因为计算而未被充分利用,也不会因为等待内存带宽而过度利用。

实际上,要真正维持盒子上打印的flop数字是几乎不可能的。我们可以使用数学来接近,但在生产中需要大量实验来微调一切。

挑战#3:衡量正确的指标
批量大小和KV缓存利用率的组合是我们关注的主要指标。这是我们用来确定服务器负载的两个数字。我们并没有一开始就得到这个指标;花了时间才发现它对我们最有效。最初,我们有一个类似于标准CPU利用率指标的更简单的gpu利用率指标。然而,它证明是误导性的,因为简单的利用率只说明了GPU在一个时间段内是否在进行数学计算。它没有告诉我们:

我们是否已经饱和了算术强度;浮点运算与总数据移动量的比率:FLOPS/字节。基本上,GPU利用率没有告诉我们我们是否在计算上未被充分利用,或者是否被内存饿死。

我们是否正在耗尽KV缓存。这是一个问题,因为有了KV缓存未命中,GPU需要进行更多的计算来计算未缓存的结果。

还有其他瓶颈。KV缓存和批量大小并不是我们发现的唯一瓶颈。在现实世界中,我们遇到了来自:

  • 内存带宽
  • GPU之间的网络带宽
  • 节点(机器)之间的网络带宽

……只是列举了三个!

让情况变得更复杂的是,瓶颈的位置经常变化。例如,要求ChatGPT总结一篇论文与要求它写一篇论文的性能特性截然不同。我们不断调整LLM变压器模型架构的特定细节,这些变化会影响瓶颈出现的地方。

在LLM的问题空间中,你会遇到的约束的变化范围出奇地广泛。这使得我们难以解决问题,也使得芯片制造商难以设计出能够实现最佳平衡的芯片。

例如,NVidia的新H100芯片是A100芯片之后的一代。H100在计算(即FLOPS)上增加了大约6倍,而内存大小保持不变,内存带宽只增加了1.6倍。由于我们经常受到内存的限制,FLOPS(和成本)的戏剧性增加往往未被充分利用。

事实是,像NVIDIA H100这样的顶级芯片今天的设计是几年前就锁定的。当H100芯片设计时,NVIDIA无法知道内存的重要性的发现,因为未来的架构很难预测。最近宣布的H200芯片增加了内存;然而,该行业花了一段时间才更好地理解这些独特的瓶颈,以大规模运行LLM。

挑战#4:在任何地方寻找GPU
与GPU相关的另一个挑战是在哪里找到它们!我们的公司——以及整个AI领域——的增长速度远远超过了供应商,如NVIDIA,或完整的TSMC供应链,可以生产GPU的速度。对于像半导体和数据中心这样复杂的供应链,瓶颈会发生在许多地方。

一种解决方案是从我们能找到的任何地方获取GPU。我们使用Microsoft Azure作为我们的云提供商,它在许多不同的地理区域和数据中心都有GPU。因此,我们很快就发现自己遍布全球的许多地区。

从第一天起,我们的小团队被迫采取多区域、多集群和全球分布的做法。我们的kubernetes集群很快就从被视为宠物转变为更像牲畜。

一个平衡良好的GPU舰队比分配附近的GPU更重要。对于ChatGPT来说,响应时间的最大瓶颈是GPU可以多快地逐个输出令牌。这意味着GPU地理位置靠近最终用户的优先级较低,因为网络请求的往返时间影响较小,而GPU“随时准备好”更重要。我的职业生涯教会了我计算在边缘的重要性,出于延迟原因。这对于这些工作负载来说不太相关,尤其是在GPU如此受限的情况下。

挑战#5:无法自动扩展
最后一个主要挑战是无法扩展我们的GPU舰队。简单地说,就是没有更多的GPU可以购买或租用,因此没有GPU可以自动扩展到。获得GPU的困难持续到今天,看起来没有缓解的迹象。需求的指数当前看起来比供应的指数大。不仅有更多的用户,而且更大的模型需要更多的计算,新技术如代理每个用户需要大量更多的计算。

所以,如果你看到ChatGPT的“我们已满载”消息,这是一个正确的陈述!这意味着我们没有地方可以扩展,因为我们当时已经利用了所有的GPU。

不幸的是,像GPT-4这样的模型需要如此多的计算,以至于GPU目前是我们唯一的选择,以便在规模上提供我们的服务。普通CPU将慢几个数量级。

5. 学到的经验

扩展ChatGPT当然不是你平均的软件工程扩展问题。然而,它一直是工程扩展的速成课,有很多经验可以在其他情况下应用。这里是我们学到的关键经验。

在早期扩展中,森林和树木都很重要。低级细节(树木),如KV缓存优化和CUDA内核,与更高级别的系统细节(森林)一样重要,例如全球数据中心战略。我们团队在堆栈中跳跃的能力——从GPU的最低级别,一直到产品决策——是至关重要的。

以一种适应性的方式考虑系统的约束。在加入OpenAI之前,我习惯于做一些事情,如:

调整系统以达到大约80%的CPU利用率指标——通常被认为是“好的”。一旦达到这个指标,就坐下来,而该指标保持不变。

自动扩展到一个“无限大”的云;意味着总是可以配置更多的机器。

优先考虑边缘计算:将其移动得非常靠近用户,以减少往返请求的延迟,并改善用户体验。

在OpenAI,这些做法都不适用!我们需要提出新的方法,这些方法既实用又易于衡量和扩展。

而且,就在我们弄清楚有效的东西时,模型架构会发生变化,或者会提出一个新的推理想法,或者产品决策会改变系统的使用方式。因此,我们需要一次又一次地适应。

深入挖掘。在我们运作的问题空间中,最低级别的实现细节真的很重要。将ChatGPT视为一个“黑盒”,它将文本作为输入,并在另一端吐出稍微聪明一些的文本,这很诱人。然而,越多的人深入到“黑盒”究竟如何工作的最小细节,我们就越能成为一个更好的团队和产品。

这还只是早期。挑战的规模只会增长。随着从GPT-2、3到4的每一次跳跃,我们需要完全新的方法来训练和运行模型以实现规模。这将在未来的版本中继续。我们所有的新模式,如视觉、图像和语音,都需要重新架构系统,同时解锁新的用例。

OpenAI的发展速度——以及整个生态系统——正在加速。我们将看到下一个10倍规模的挑战是什么!

ChatGPT的工作方式并不神奇,值得了解。像大多数人一样,我第一次尝试ChatGPT时的反应是它感觉很神奇。我输入了问题,并得到了感觉像是来自人类的答案!ChatGPT在处理人类语言方面做得非常出色,并且可以访问比任何一个人都多的信息。它在编程相关的问题上也很擅长,有一段时间我怀疑ChatGPT是否可以在编程等领域比人类更有能力,直到现在?

为了了解ChatGPT的局限性,你需要了解它是如何工作的。ChatGPT和其他LLM不会像人类那样“思考”和“理解”。然而,ChatGPT确实会根据下一个最可能的单词是什么,根据输入和到目前为止生成的所有内容来生成单词。

在关于ChatGPT如何工作的一篇精彩深入文章中,WolframAlpha的创造者Stephen Wolfram总结了ChatGPT:

“ChatGPT的基本概念在某种程度上相当简单。从网上、书籍等处获取大量人类创建的文本样本。然后训练一个神经网络生成“类似于此”的文本。特别是,让它能够从一个“提示”开始,然后继续输出“像它所训练的那样”的文本。

正如我们所看到的,ChatGPT中的实际神经网络由非常简单的元素组成——尽管有数十亿个。神经网络的基本操作也非常简单,基本上由将输入派生自到目前为止生成的文本“一次通过其元素”(没有任何循环等)的每一个新单词(或单词的一部分)生成。但令人惊讶的是——出乎意料的是——这个过程可以产生成功地“类似于”网络、书籍等上的文本。

ChatGPT的具体工程使其相当引人注目。但最终(至少在它可以使用外部工具之前)ChatGPT只是从它积累的“常识统计”中提取出一些“连贯的文本线索”。但结果的人类化程度令人惊叹。”

扩展ChatGPT的工程挑战是可以理解的。当扩展一个系统时,这些是常用的技术:

  • 通过交换内存以节省重复的、昂贵的计算操作(记忆化),反之亦然;如果内存不足且有大量未使用的计算,使用计算来节省内存
  • 购买更多硬件以横向扩展
  • 找出要衡量的正确事物,并进行改进,使这些指标朝着正确的方向发展;冲洗并重复

OpenAI的工程团队采用了所有这些技术来扩展该产品。

一些扩展挑战可以简化为解决一个数学问题。在挑战#2中——优化批量大小——解决最大利用率的问题归结为在操作和内存带宽之间进行最大化。一旦你知道了操作和内存带宽的值,这就成了一个优化练习。

当面临优化效率的挑战时,可以从这种方法中汲取灵感。弄清楚你的系统的特性——吞吐量、延迟、CPU利用率、内存利用率和其他相关值——并弄清楚改变一个将如何改变另一个。更高的CPU利用率(使用更少的机器)意味着什么?每台机器增加或减少内存会怎样?等等。

即使是OpenAI也在努力寻找GPU硬件。大型语言模型需要大量的计算,GPU芯片是这种用例最适合的硬件。今天,NVIDIA的H100——一种高性能GPU——是大多数投资大量AI的公司的硬件选择。

对H100的需求超过了供应,尤其是像Meta这样的公司在获取它们上花费了巨额资金。我们最近报道了Meta希望到2024年底拥有350,000个H100单位。

尽管与Microsoft有着强大的合作伙伴关系并拥有大量资金,OpenAI也面临着获取足够GPU的挑战。

NVIDIA应该从需求中获得巨大利润,但我们可以期待其他玩家加大力度,设计芯片与之竞争。实际上,Meta正在构建自己的定制AI芯片,AWS也是如此。主要芯片制造商也没有闲着:AMD在2023年12月推出了MI300X处理器,早期基准测试显示其性能优于H100。Intel正在开发Gaudi3处理器,旨在与H100竞争,并计划在2024年晚些时候推出。

尽管有新GPU进入市场,但扩大大规模生产还需要更多时间。AI领域的公司可能在未来一两年内仍然可以预期GPU的稀缺。

由于硬件稀缺而导致的工程挑战往往会导致巧妙的解决方案。今天,由于云提供商的存在,几乎没有软件工程师熟悉硬件稀缺,因为没有计算或存储容量的短缺。如果需要更多的CPU或存储,问题是它将花费多少,而不是是否有容量可用。

同时,我们之前也看到了行业范围内硬件稀缺的挑战。这样的约束促使工程师提出巧妙的效率胜利。例如,虚拟化诞生于更好地利用硬件资源的努力,正如我们在《现代后端实践的过去和未来》中所涵盖的那样。

我希望看到OpenAI等公司因必要而产生的更多巧妙解决方案,这将导致即使是更复杂的AI应用也需要更少的计算。我对应用AI应用带来的未来感到兴奋,但希望实用的AI应用不需要消耗比当前计算基础设施多几百倍的能源来运行的计算基础设施。计算机是高效的机器,可以用相对较少的能源完成大量工作。希望我们保持这种方式,即使在构建更好、更有能力的AI应用的竞赛中也是如此。

相关文章:

产品化Chatgpt所面临的五大技术挑战

2022年11月,ChatGPT横扫全球,成为应用人工智能(AI)领域迄今为止最令人惊叹的“哇!”时刻,也是当前科技投资激增的催化剂。2023年11月,首席执行官Sam Altman宣布该产品周用户量达到1亿&#xff0…...

8.qt5使用opencv的库函数打开图片

1.配置opencv动态库的环境变量 2.在创建的qt工程中加入如下opencv代码,具体代码如下: 使用opencv库函数显示图片...

学习 python的第四天,顺便分享两首歌:we don‘ talk anymore,You ‘re Still The One

诸君晚上好,现在是🌃晚上,今天是学习python的第四个学习日,不知不觉学了四天了,还是那句话:不积跬步无以至千里、不积小流无以成江海! 暂时回顾下前面的学习日吧: 第一个学习日----…...

uniapp:APP端webview拦截H5页面跳转,华为市场发布需要限制webview的H5页面跳转

在使用uniapp开发APP项目时,华为市场上线APP会被打回来:您的应用内容存在点击跳转至第三方应用市场或游戏中心下载渠道的问题,不符合华为应用市场审核标准。 华为审核指南4.6 因此可以考虑下面的处理方式,通过拦截webview页面的…...

[HTML]Web前端开发技术28(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的…...

计算机网络实验六 OSPF

一、实验目的和要求 1、掌握 OSPF 的基本配置方法; 2、理解 OSPF 的工作原理。见实验指导书 二、实验环境 1、运行 Windows 2008 Server/XP/7 操作系统的 PC 一台。 2、PacketTracer。 三、实验内容与过程(实验题目和代码) 实验内容: 根据以下任务配置网络:某单位拥…...

亿道丨三防平板丨加固平板丨为零售业提供四大优势

随着全球经济的快速发展,作为传统行业的零售业也迎来了绝佳的发展机遇,在互联网智能化的大环境下,越来越多的零售企业选择三防平板电脑作为工作中的电子设备。作为一种耐用的移动选项,三防平板带来的不仅仅是坚固的外壳。坚固耐用…...

RK3568平台开发系列讲解(Linux系统篇)SPI 客户端通信

🚀返回专栏总目录 文章目录 一、spi_transfer二、spi_message三、初始化沉淀、分享、成长,让自己和他人都能有所收获!😄 SPI I/O模型由一组队列消息组成。我们提交一个或多个struct spi_message结构时,这些结构以同步或异步方式处理完成。单个消息由一个或多个struct sp…...

MySql-DQL-聚合函数

目录 聚合函数统计该企业员工数量count(字段)count(常量)count(*) 统计该企业最早入职的员工统计该企业最迟入职的员工统计该企业员工 ID 的平均值统计该企业员工的 ID 之和 聚合函数 之前我们做的查询都是…...

Java:获取PDF文件的总页数

引入依赖 <!--pdf--> <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.24</version> </dependency>代码工具类 package com.example.util;import org.apache.pdfbox.p…...

Git介绍与使用

Git介绍与常用命令的使用 目录: 一、Git简介 二、Git简单命令行入门 三、Git常用命令 四、常见问题补充 一、Git简介 Git 是一个开源的分布式版本控制系统&#xff0c;是目前世界上最先进、最流行的版本控制系统。可以快速高效地处理从很小到非常大的项目版本管理。特点&…...

React18源码: React中的LanePriority和SchedulerPriority

优先级区别和联系 在源码中&#xff0c;3种优先级位于不同的js文件&#xff0c;是相互独立的注意&#xff1a; LanePriority 和 SchedulerPriority 从命名上看&#xff0c;它们代表的是优先级ReactPriorityLevel 从命名上看&#xff0c;它代表的是等级而不是优先级 它用于衡量…...

Android Studio基础(下载安装与简单使用)

1、搭建Android开发平台 1.1 Android Studio 下载地址及版本说明 Android 开发者官网&#xff1a; https://developer.android.com/index.html&#xff08;全球&#xff0c;需科学上网&#xff09; https://developer.android.google.cn/index.html&#xff08;国内&#xff…...

MyBatisPlus条件构造器和常用接口

前置配置文章 一、wapper介绍 wrapper的继承体系&#xff1a; Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 QueryWrapper &#xff1a; 查询条件封装UpdateWrapper &#x…...

ABAP 导入Excel表示例程序

目录 ABAP 导入excel示例程序创建程序使用的结构上传下载模板 ABAP 导入excel示例程序 批量导入程序&#xff0c;需要使用到导入模板&#xff0c;首先需要创建程序&#xff0c;之后是需要创建excel导入模板&#xff0c;并且需要将excel导入模板上传到SAP系统里面&#xff0c;之…...

Spring之AOP源码解析(中)

前言 在上一篇文章中,我们讲解了Spring中那些注解可能会产生AOP动态代理,我们通过源码发现,完成AOP相关操作都和ProxyFactory这个类有密切关系,这一篇我们将围绕这个类继续解析 演示 作用 ProxyFactory采用策略模式生成动态代理对象,具体生成cglib动态代理还是jdk动态代理,…...

《Docker极简教程》--Docker卷和数据持久化--Docker卷的使用

一、基本操作 1.1 创建Docker卷 创建 Docker 卷是在 Docker 中管理持久化数据的重要步骤之一。通过 Docker 卷&#xff0c;可以将数据与容器解耦&#xff0c;实现数据的持久化存储&#xff0c;并且可以在容器之间共享数据。以下是创建 Docker 卷使用 docker volume create 命…...

【Logback】如何在项目中快速引入Logback日志?

目录 1、引入相关依赖或者 jar 包 2、使用logback日志 3、引入logback配置文件 4、打印logback内部状态信息 Logback 是 Java 社区中使用最广泛的日志框架之一。它是其前身 Log4j 的替代品。Logback 比所有现有的日志框架速度更快&#xff0c;占用空间更小&#xff0c;而且…...

【Linux从青铜到王者】 基础IO

本篇重点&#xff1a;文件描述符&#xff0c;重定向&#xff0c;缓冲区&#xff0c;磁盘结构&#xff0c;文件系统&#xff0c;inode理解文件的增删查改&#xff0c;查找一个文件为什么一定要有路径&#xff0c;动静态库&#xff0c;有的时候为什么找不到库&#xff0c;动态库的…...

C++之类作用域

目录 1、全局作用域 2、类作用域 2.1、设计模式之Pimpl 2.2、单例模式的自动释放 2.2.0、检测内存泄漏的工具valgrind 2.2.1、可以使用友元形式进行设计 2.2.2、内部类加静态数据成员形式 2.2.3、atexit方式进行 2.2.4、pthread_once形式 作用域可以分为类作用域、类名…...

SpringCloud Gateway网关 全局过滤器[AntPathMatcher 某些路径url禁止访问] 实现用户鉴权

前提&#xff1a;先保证Gateway网关项目 和 Nacos注册中心 等可以正常访问和调用&#xff0c;搭建方法可查看博文SpringCloud Gateway网关 项目创建 及 整合Nacos开发_spring gateway如何设置工程名称-CSDN博客 类似的全局鉴权方案&#xff0c;参考如下&#xff1a; SpringClo…...

ELK介绍以及搭建

基础环境 hostnamectl set-hostname els01 hostnamectl set-hostname els02 hostnamectl set-hostname els03 hostnamectl set-hostname kbased -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config systemctl stop firewalld & systemctl disable firewalld# 安…...

Spring中的ApplicationContext.publishEvent

简单理解 其实就是监听处理。比如找工作平台上&#xff0c;雇主 employer 发布自己的雇佣条件&#xff0c;目的是平台中有符合条件的求职者时&#xff0c;及时向雇主推荐。求职者发布简历&#xff0c;当平台发现某个求职者比较符合条件&#xff0c;就触发被动&#xff0c;推荐…...

jackson、gson、fastjson和json-lib四种主流json解析框架对比

一、四种框架的介绍和对比 在Java中&#xff0c;Jackson、Gson、Fastjson和json-lib都是流行的JSON解析框架&#xff0c;它们各自有一些特点和优势。下面是对它们进行简要介绍和对比&#xff1a; 1.1 介绍 1&#xff09; Jackson: Jackson是由FasterXML开发的一个高性能的J…...

已解决:IDEA中@Autowired自动注入MyBatis Mapper报红警告的几种解决方法

今天在使用 IDEA 使用 MyBatis 的时候遇到了这种情况&#xff1a; 可以看到 userMapper 下有个红色的波浪警告&#xff0c;虽然代码没有任何问题&#xff0c;能正常运行&#xff0c;但是这个红色警告在这里杵着确实让人很窝心。 于是我在网上找了找&#xff0c;最终明白了原因…...

在jar里限制指定的包名才可调用(白名单)。

1. 在jar包中定义一个接口&#xff0c;例如 用于检查传入的hash值是否匹配预设的值。 2. 在调用接口的地方&#xff0c;获取当前应用的hash值。 3. 将当前应用的hash值与预设的值进行比较&#xff0c;如果匹配&#xff0c;则允许调用接口&#xff1b;否则&#xff0c;拒绝调用。…...

python 提取PDF文字

使用pdfplumber&#xff0c;不能提取扫描的pdf和插入的图片。 import pdfplumberfile_path rD:\UserData\admindesktop\官方文档\1903_Mesh-Models-Overview_FINAL.pdf with pdfplumber.open(file_path) as pdf:page pdf.pages[0]print(page.extract_text()) # 所以文字prin…...

电气机械5G智能工厂数字孪生可视化平台,推进电气机械行业数字化转型

电气机械5G智能工厂数字孪生可视化平台&#xff0c;推进电气机械行业数字化转型。随着科技的不断发展&#xff0c;数字化转型已经成为各行各业发展的重要趋势。电气机械行业作为传统制造业的重要组成部分&#xff0c;也面临着数字化转型的挑战和机遇。为了更好地推进电气机械行…...

C# (WebApi)整合 Swagger

SpringBoot-整合Swagger_jboot整合swagger-CSDN博客 C# webapi 也可以整合Swagger webapi运行其实有个自带的HELP页面 但是如果觉得UI不好看&#xff0c;且没办法显示方法注释等不方便的操作&#xff0c;我们也可以整合Swagger 一、使用NuGet控制台安装Swagger 在菜单中选择…...

导入excel某些数值是0

目录 导入excel某些数值是0数据全部都是0原因解决 部分数据是0原因解决 导入excel某些数值是0 数据全部都是0 有一列“工单本月入库重量”全部的数据都是0 原因 展示的时候&#xff0c;展示的字段和内表需要展示的字段不一致&#xff0c;导致显示的是0。 解决 修改展示的字…...