《Roller: Fast and Efficient Tensor Compilation for Deep Learning》
《Roller: Fast and Efficient Tensor Compilation for Deep Learning》
用于深度学习 快速高效的张量编译器
作者 微软亚洲研究院以及多伦多大学等多所高校
摘要
当前编译为了产生高效的kernel时,搜索空间大,通常使用机器学习的方法 找到最优的方案,导致编译器时间长,通常需要几天甚至几周的时间。
ROLLER, 使用基于构造的方法产生kernel,速度快,仅需要数秒。
提出rTile, 一种新的tile抽象,封装了tensor shape, 和底层加速器关键特征一致。
使用基于rTile的算法递归构造rProgram
tile就是对输入进行分块以适应硬件的内存结构
1. 前言
DNN 编译器(cuDNN cuBLAS)是为了产生更高效的kernel, 减少人工kernel库的开发。编译优化通常在循环计算中使用 分块/融合/重排等, 但是编译时间长。
本文基于以下三个观点提出ROLLER
1 相比多级嵌套,ROLLER将DNN算子的计算作为数据处理管道,数据块在抽象的硬件(具有并行执行单元和多层内存结构)中移动和处理
2 为了让加速器更加高效,数据块的shape应该和硬件特征(memory bank,memory transaction length, and minimum schedulable unit )保持一致
3 pipline对齐后的的性能是可预测的
提出 rTile,rProgram posed by three interfaces: Load, Store, and Compute
2. 动机
超长的编译时间
Ansor单算子平均编译时长0.65小时,其中ResNet中一个卷积算子编译时长2.17小时。一个DNN网络可能有上百个算子,需要几天的时间编译。比如 NASNet 模型,编译时间41.8小时,获得了38%的提升。
观察和发现
3. 系统设计
Roller的输入是使用TE表达式。该表达式由用户生产或者从其它编译器生成(这一步可能会发生一些融合操作)。
Roller从TE中提取张量形状并基于硬件规范来构建rTiles,即对齐硬件的构建块。基于rTiles,Roller提出了一种横扩纵扩递归构造算法,用于生成描述数据处理管道的高效张量化程序(rProgram)。
在生成rProgram时,构建算法通过微观性能模型评估构建的rProgram的性能,从而识别出良好的rTile配置。它建立在通过硬件抽象描述的设备上,仅公开和rTiles相关的接口:Load/Save/Compute。构建的rProgram最终通过Codegen生成特定设备的最终Kernel。
3.1 张量表达式和 rTile
Roller将TVM中引入的Tensor Expression引入作为编译器的输入
rTile封装了给定张量表达式的expr的每个循环轴定义的多维tile shape。给定shape和expr,rTile可以静态推断所涉及的输入和输出数据块。
与hardware execution unit对齐
rTile的shape必须和它运行的执行单元的并行度对齐。例如,在GPU上运行 rTile 的shape 大小必须是 wrap size的倍数,比如 32 来达到最大的计算效率。当在NVIDIA GPU中使用TensorCore时,rTile shape大小应该是 16x16x16 的倍数。
与memory transaction对齐
对于rTile的每个数据块我们都应该保证它的Leading dimension(如行优先Tensor中的最内层维度)是内存事务长度的倍数。如Figure5(a)所示,在Roller中,张量内存以缓存对齐的方式分配。因此,rTile可以避免浪费任何的内存读取,因为它的 shape 是和内存事务长度对齐的。
与memory bank 对齐
避免读取冲突。例如,在数据块a(shape为[3, 4] )跨4个bank保存在内存中,并由形状为 [3, 1] 的块读取。将这个形状为[3, 1]的小块中的数据存储在一个bank的naive方法将导致加载冲突。rTile通过padding来避免这种低效。给定一个Leading dimension为N的数据块,由另外一个Leading dimension为n的块读取,我们延N维度做一个padding_size大小的padding。
与tensor shape对齐
rTile的shape应该和输入张量表达式的张量shape对齐。否则,计算不能被rTile均匀且分,浪费计算资源或者产生大量的边界检查开销。
Deriving all rTiles
vector<int> GetNextAlignedAxisSize(rTile T, Dev d)
计算数据重用分数
更大的Si 表示在使用相同的内存时可以节省更多的内存流量。内存重用分数在构建高效的 rProgram(使用 rTiles)中起着至关重要的作用。
3.2 张量程序构造
rTileProgram
给定 rTile 和现代加速器的内存分层结构,张量计算可以自然地被看成数据流处理管道。
Figure6 展示了具有三个存储层(L0,L1,L2)的设备上的rProgram。rProgram由每个 内存层次 的 rTile 和 rTile 指令(Load, Store, Compute) 来描述。
Figure7(a)展示了Figure7(b)对应的MatMul程序。Figure7©说明了rProgram如何映射到设备的每个内存层次。具体来说,每次它从内存L2中加载一个A的4x4小块和B的4x8小块到L1中。然后从L1中加载一个A的2x1和B的1x2小块到L0(寄存器)中。每次计算完成后,结果的2x2小块会直接从L0写回到L2。
给定一个数据处理流水线,对应的rProgram的优化目标就是最大化流水线的吞吐量。这个目标可以转化为满足三个条件:
1)计算和内存移动应该充分利用硬件的特性
2)吞吐量应该达到瓶颈(接近峰值)
3)需要有足够的并行度来利用所有的并行执行单元
因此,Roller提出以下rProgram的构建策略:首先通过构建单核 rProgram在一个内核上纵向扩展,使得Kernel的硬件利用率饱和。然后通过复制构建的单Kernel横扩以利用硬件的并行度。
Scaling up an rProgram
由于rTile的对齐属性确保了硬件的效率,Roller可以只专注于通过构建正确的rTile shape来最大化每个内存层次的吞吐量。通过利用0x3.1节中定义的数据重用分数,单核rProgram构建算法从初始化rTile开始,并逐渐将其扩大到rTile中收益最大的轴(也即具有最大重用分数的)。注意,构造算法不需要精确的数据重用分数,它只是选择最大的一个来最大化吞吐量。在此过程中,内存的性能会提高直到达到计算峰值或者最大的内存容量。上述过程从上到下对每个内存层次进行重复,直到构建出所需的rProgram。请注意,如果某些张量表达式的数据重用分数保持不变,比如elemetwise算子,Roller将只为顶层构建rTiles并从底层内存内存加载它们。
给定一个张量表达式expr和目标设备dev,该算法在顶层内存构造一个初始化的rTile T并递归的放大T(对应第4行的EnlargeTile)。
每一步,它都会枚举下一个更大的rTile T‘,最大程度的提高数据重用得分(对应第10行的GetNextRTileShapes)。
如果T’达到内存容量(第13行)或者数据块加载的吞吐量MemRef(T’)超过了峰值计算吞吐量 MaxComputePer f(T’)(第17行),
算法记录当前的rTile并在下一个内存级别继续EnlargeTile。否则,它会在当前内存层级继续扩大T’(第20行)。
构建在最低的内存层级完成(第6行),产生一个结果并重复运行直到产生K个rPrograms(来包容编译器的隐藏因素影响)
注意,MemPer f(T′)和MaxComputePer f(T′)是基于3.3节的微评测模型推导出来的。
Scaling out an rProgram
考虑大多数DNN算子计算模式和加速器中并行执行单元的的同质性, Roller 简单地将在一个执行单元上构建的 rProgram 复制到其他单元。
Roller 通过将计算统一划分为大小等于最低内存层级 rTile 的 rTiles。
通过将所有rTiles平均分配到所有执行单元来实现这一点。注意,Roller更喜欢将reduce轴分配到同一执行单元上,因为它们可以在更高的内存层级中共享recue的结果。
采用基于rTile的递归构造方法(Figure8)逐渐增加rTile shape大小,来构造一个饱和加速器单个执行单元(如SM)的rProgram
Small operator and irregular tensor shape
对于小算子,算法的整体性能kennel会受到并行执行单元利用率低的影响。这里可以通过Rammer编译器的同时调度一些小Kernel来解决。然后另外一种方法是对于每个rProgram,Roller尝试沿着具有最小数据重用分数的轴收缩rTiles,来实现足够的并行度。
大算子可能包含不规则的尺寸较小的张量维度,而Roller由于对齐要求kennel无法生成足够数量的rProgram。为了解决这个问题,Roller通过轴融合pass将张量表达式转换为规范的形式。具体来说,对于所有设计的张量,如果在一个张量中存在两个相邻的轴,这些轴在所有的其它张量中既存在又相邻,或者都缺失,Roller就可以安全的合并这两个轴。如,一个输入和输出张量形状都是[17, 11, 3]的张量,Roller会把这三个维度fuse起来变成[ 561 ] ( 17 × 11 × 3 ) 。
3.3 Efficient Evaluation of an rProgram
在构建算法中,Roller需要评估rProgram的性能。Roller无需评估真实硬件设备中端到端的rProgram,只需要评估 rTile 的性能,如Figure8中的MemPerf和MaxComputePerf。
Roller针对硬件抽象层(HAL)中描述的设备构建了一个微评测模型。HAL将加速器建模为具有分层内存的多个并行执行单元,HAL公开了三个基于rTile的接口:Load,Save,Compute。执行单元被抽象为rTile Execution Unit(TEU),它通过Compute接口对数据块进行计算。可以将多个TEUs组织为一个组,它们可以协同加载和存储Tiles。HAL将不同的内存层(如寄存器,共享内存,DRAM)视为一种统一类型,暴露了影响Tile性能的硬件规范。硬件规范包括内存容量,事务长度,缓存行大小,Memory Banks数量,可以通过Figure9的getDeviceSpec获取。
微评测模型
借助硬件抽象层,Roller可以轻松推导出rTile(和rProgram)的性能。
首先,给定一个rTile,可以从rTile的张量表达式expr和shape静态推断出产生的内存占用(包括padding,Figure9中的MemFootprint)和跨不同层的内存流量(Figure9中的MemTraffic 接口)。计算数据重用分数并检查rTile是否已经超出内存容量。
其次,为了计算rTile的MaxComputePerf,Roller通过积极扩大Tiles shape使得TEU饱和,进行一次性分析以测量峰值计算吞吐量。此性能数据缓存在Roller中,供将来在构造算法中查询。
最后,对于给定的rTile,Roller还估计MemPerf,即从内存低层加载到更高层的性能。给定rTile中对齐的内存访问,加载常规Tile的延迟可以简单地通过将总流量除以内存带宽来建模。对于所有TEU共享的内存层,我们平均分配带宽。对于较小的访问内存,Roller对每种设备类型进行一次离线分析并缓存结果。
值得注意的是,微观性能模型只需要在Tile shape完全对齐的情况下准备,这是Roller的关键要求。
4 实现
实现基于TVM和Rammer,
ROLLER实现机制包含 :expression optimization, construction algorithm, micro-performance model
-
输入是一个ONNX图或TensorFlow图。
-
首先ROLLER利用Rammer进行图优化;
-
然后ROLLER为每个(融合的)运算符 派生TVM张量表达式,并通过构造算法生成相应的rProgram,进行kernel生成;
-
最后,生成的内核被注入Rammer的运行时并生成端到端模型代码
代码生成(Code generation)
给定固定的代码结构(如Figure6中的一个rProgram),Roller基于预定义的模板生成代码(TVM 内置调度原语)。在每个内存层级加载和存储数据块由 TVM 的 cache_read 和 cache_write 原语实现。rTile 上的分区是通过 split 和 fuse 完成的。 一些rTile计算的原语是通过TVM内置API完成的。基于模板,给定的rProgram可以直接生成cuda代码。
张量填充(Tensor padding)
Roller依靠张量padding将rTiles和张量shape对齐。在实践中,最底层内存(例如 DRAM)中的大多数张量是由外部程序(例如 DNN 框架)分配的,因此我们只需在上层内存(例如共享内存)中应用padding。 Roller的张量padding目前需要输入张量表达式来指定它是否允许填充,以及默认的填充值(例如,0 表示 MatMul 运算符)。 对于 Memory Bank 对齐的storage padding,我们利用 TVM 的 storage_align 原语添加padding。
性能分析器
Roller实现了两个性能分析器。
微性能分析器:通过micro-benchmark生成内存带宽,计算吞吐量等硬件指标。这是针对每种设备类型和张量表达式的一次离线分析。
内核分析器:描述了top K个kPrograms中最快的kernel.如果k大于1则用于每一个编译结果。在实际应用中,特定内核代码的性能也会受到设备编译器和硬件相关隐藏因素的轻微影响,Roller 几乎无法控制。这些因素包括不同指令类型的指令密度、寄存器分配行为、设备编译器优化、warp 调度开销等。特别是在 NVIDIA GPU 上,Roller 依靠 nvcc 将生成的 CUDA 代码编译成机器代码。 但是,nvcc 的专有优化可能会对程序执行行为产生不利影响。 因此,Roller 利用内核分析器快速评估性能最佳的 rProgram 并选择最佳的。 较大的 K 通常可以提高kernel质量。在评估前 10、20 和 50 个结果后,我们的经验表明,前 10 名可以获得大多数情况下的最佳结果。 请注意,Roller 的内核分析器不同于以前编译器中由机器学习算法驱动的评估过程 。 基于 ML 的方法通常需要数百甚至数千个顺序评估步骤,而 ROLLER 仅并行分析数十个候选者。 未来,我们计划实现汇编级代码生成,以缓解高级设备编译器中的隐藏问题。
ROLLER on NVIDIA CUDA GPUs
The transaction length at the global memory layer is set to 32 Bytes
the bank number is 32 Bytes
the bank length is 4 Bytes
ROLLER on AMD ROCm GPUs
ROLLER on Graphcore IPUs
5 评测
- 和TVM Ansor相比,编译时间是数量级的减少,最耗时的算子需要43s, 同时其他算子耗时13s.
- ROLLER 获得了当前最好的性能,甚至50%的情况下优于其他编译加速器
- 针对小size和不规则的shape, 效果不是很明显,是由于很难和硬件参数对齐。但本身这些算子的耗时也较少(小于1ms)
- 我们进行了广泛的评估,覆盖不同加速器上的不同算子(共119个算子)
Experimental setup
Benchmarks.
5.1 NVIDIA GPUs评估
算子性能
cuda上的结果,119 个算子的平均kernel性能,按算子类型和 ID 排序。我们将大型算子(例如,kernel时间大于 5ms)绘制在 y 轴为对数尺度的顶部子图中,而底部 4 个子图是其它中小型算子。
首先,与 CUDA 库 (CudaLib) 相比,Roller 可以为 81.5% 占比的算子获得可比的性能(即在 10% 以内),并且对于 59.7% 的算子来说甚至更快。
我们观察到,Roller 表现较差的大多数算子是具有 3×3 或更大滤波器的卷积算子,它们通常在 cuDNN 中使用更有效的数值算法(例如,Winograd [23])来实现,并且难以用张量表示表达。这就是在这些情况下 Ansor 和 TVM 也比 CudaLib 慢的原因。
其次,与 TVM 和 Ansor 相比,Roller 也可以分别为 72.3% 和 80.7% 占比的算子获得可比的性能。其余的 27.7% 和 19.3% 主要是小算子或张量形状不规则,难以与硬件对齐。然而,这些算子的kernel执行时间通常相对较短,例如平均只有 1.65 毫秒和 1.16 毫秒。在所有算子的 54.6% 和 65.5% 占比中,Roller 甚至可以分别比 TVM 和 Ansor 生成更快的kernel。我们观察到这些算子中的大多数都是大型且耗时的。正如上面的子图所示,当算子大于 5 毫秒(最高 343 毫秒)时,Roller 可以为这些算子中的大多数实现更好的性能,例如,与 TVM 和 Ansor 相比,平均速度提高了 1.85 倍和 1.27 倍。
编译时间
编译的平均时间,相比于TVM和Ansor,Roller的算子编译时间在数秒内,比TVM和Ansor的搜索时间快了2个数量级。
Scale-out with operator size
对于MatMul算子,Ansor和ROLLER在batch sizes上线性可伸缩性,且性能和CudaLib(即cuBLAS)相当。但是,TVM的性能相对不稳定。
对于Conv2D算子,ROLLER仍然可以实现batch sizes上线性可伸缩性,并获得比Ansor和TVM略好的性能(平均为1.25和1.54×)。注意此类型的有效内核,Anosr无法搜索,使用默认配置,批处理大小超过2048。
TVM和Ansor的平均编译时间为2.36小时(最长9.55小时)和1.19小时(最多3.0小时)。
而且,它们的编译时间随着batch size大小的增加而不断增加。这是因为它们都是基于ML的搜索方法,其搜索空间通常随着算子呈指数增长。相比之下,ROLLER在1秒内产生top-1 kernel,产生top-10 kernel平均需要16秒(最多34秒)。
在TensorCore上编译
小算子和不规则张量形状
小算子上比Ansor慢,比TVM快
微评测模型
Micro-performance model 和真实设备的对比
Kernel 性能
端到端模型性能
如下展示了几个经典的神经网络的性能和编译时间,可以发现Rooller相比于TVM和Ansor可以获得相当的性能,但可以将编译时间从几十个小时缩短到几百秒钟,可以大大提高模型的实际生产周期。
Operator performance on K80 GPUs.
5.2 对其他加速器的评估
Operator performance on AMD ROCm GPUs
Operator performance on Graphcore IPU
6 讨论与未来工作
Optimization space compared with loop-based compiler
Optimization trade-off
Future work
7 相关工作
大多数张量编译器将DNN 算子视为嵌套的多层循环计算,这本质上定义了一个具有组合复杂性的大空间。
TVM继承了Halide的这个观点,并将DNN操作符描述为循环优化调度原语。
后来,AutoTVM扩展 TVM,应用机器学习的方法从手动编写的代码模板中搜索最佳配置图。
FlexTen提出自动探索空间而不用手工模板。
Ansor进一步推进了这种自动化。它生成一个更大的搜索空间,考虑到分层编码结构,采用进化算法查找性能内核。
像Tiramisu,AKG,和Tensor Comprehensions这样的编译器,将循环视为整数规划问题,并用求解器找到一个好的配置。
所有这些方法都依赖于巨大的搜索空间来产生好的kernel,这就导致了编译/求解时间长。
ROLLER探索了不同的构造与硬件特性一致的rtile的方法。
张量处理原语(TPPs)定义了一组2d -张量算子用于在高维张量上组成复杂算子,提供有限的表达。
相比之下,ROLLER不限制tile shape 维度可以应用于一般张量表达式。
OpenAI的Triton是一个用于开发基于块的GPU内核的编程框架和编译器。Triton依赖于程序来决定区块大小和区块调度,
ROLLER同时将硬件特征和张量形状两者都考虑进去。
MLIR和Tensor IR计划在IR中支持块计算表示。ROLLER的rTile抽象和程序建设与这些举措相兼容。
图级DNN编译器,如XLA, TVM,和Rammer专注于跨操作优化,例如,算子融合/ co-scheduling。
ROLLER的核生成为与这些编译器兼容。
ROLLER的rTile抽象补充Rammer中的rTask概念,一种构造rTask的有效方法。
最后,一些工作侧重于特定算子优化方案。
CUTLASS是实现矩阵乘积的模板,提出了仅适用于多核cpu上的卷积运算符的最佳循环级优化配置一个解析模型。
DREW 提出了一种数据压缩优化Winograd卷积的新方法。
ROLLER的优化方法在各种设备上的DNN操作符上是通用的。
8 结论
ROLLER采用了一种和常规的深度学习方法编译器不同的思路。
ROLLER并未使用耗时的机器学习算法来在大的搜索空间中找到最优解决方案,ROLLER使用基于递归结构的算法生成有效的内核。
该算法利用了新的rTile抽象 ,将少量shape与多种硬件特征进行对齐。
所构造的程序可以用微观评估模型机进行评估,而无需在真实设备上运行。
因此,ROLLER可以进行高性能的编译,即使在不太成熟的加速器中,内核也可以在几秒内完成。
更重要的是,ROLLER为新的AI硬件供应商提供了独特的和显著有效的方法,可以构建具有竞争力的供应商特定的DNN库,
接入生态减少与市场领导者的差距,从而促进AI加速器创新。
相关文章:
《Roller: Fast and Efficient Tensor Compilation for Deep Learning》
《Roller: Fast and Efficient Tensor Compilation for Deep Learning》 用于深度学习 快速高效的张量编译器 作者 微软亚洲研究院以及多伦多大学等多所高校 摘要 当前编译为了产生高效的kernel时,搜索空间大,通常使用机器学习的方法 找到最优的方案…...
顺丰同城测试开发一面 49min答案,全文7000字,面试总结都在这里了
今天给大家分享一份顺丰同城的测试开发一面面试真题。老规矩,当你看到这份面试题的时候,先不要着急去看答案,你可以想想假如你在面试现场,你会怎么回答?这个思考的过程其实也是很重要的。 全文7000字干货,…...
docker启动容器服务之后访问失败
关于docker启动容器服务之后,宿主机访问失败(解决方法) 注:在进行docker容器启动宿主机进行容器访问时,无需进行网络的配置,docker容器在启动时会自动解决 第一种原因及修改方法 在进行启动的时候&#…...
GraalVM-云原生时代的JVM(Java)
文章目录一、GraalVM是什么?二、GraalVM有哪些特点?2.1、高性能2.2、多语言支持2.3、互操作性2.4、安全性三、GraalVM的应用效果3.1、提高性能3.2、简化开发3.3、降低成本3.4、节省资源3.5、支持云环境四、使用GraalVM编译springboot应用程序4.1、下载并…...
如何外网登录访问瑞友天翼应用虚拟化系统?——快解析内网端口映射方案
瑞友天翼应用虚拟化系统(GWT System)是国内具有自主知识产权的应用虚拟化平台,是基于服务器计算(Server-based Computing)的应用虚拟化平台。如何将内网平台提供到互联网上外网访问,是我们比较关注的问题。…...
蓝海彤翔执行副总裁张加廷接受【联播苏州】独家专访
今年春节档,科幻类电影《流浪地球2》票房口碑双丰收,截至目前,累计票房已破 38 亿,淘票票评分 9.6 ,影片的特效质感可以媲美国际顶尖水平。其中,蓝海彤翔为影片的后期制作提供了出色的渲染服务。2月21日&am…...
iOS Airplay Screen Mirroring 同屏技术详解
投屏技术已经被大量用在身边的产品,比如电视投屏,投影仪,视频会议产品中。 在iOS平台外的其他平台中都已经有非常成熟的标准和实现。但在封闭的苹果iOS和Mac系统中,苹果使用私有的Airplay协议进行多屏互动,只开放给自己…...
更新 Python 100道基础入门检测练习题【下篇】(附答案)
前言 大家早好、午好、晚好吖 ❤ ~ 爆肝更新 Python 100道基础入门练习题【篇上】 更多精彩内容、资源皆可点击文章下方名片获取此处跳转 实例021:猴子偷桃 题目: 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半…...
[RDMA-高级计算机网络report] Congestion Control for Large-Scale RDMA Departments
本文主要解决的问题是在RoCEv2体系中,基于优先级的拥塞控制PFC是一种粗粒度的机制。 它在端口(或端口加优先级)级别上运行,并且不区分流。PAUSE机制是基于每个端口(和优先级)的,而不是基于每个流…...
ROS2功能包Hello world(python)
文章目录环境准备Python创建工作空间、功能包及节点方法编译使用环境准备 为了便于日后复现,相关环境已经打包到docker中。 拉取docker镜像 docker pull 1224425503/ros2_foxy_full:latest新建容器 docker run -dit --rm --privilegedtrue --network host -e NV…...
数学建模竞赛的一些心得体会
1.数学建模经验首先简要的介绍一下我的情况。数学建模我也是在大一暑假开始接触的,之前对其没有任何的了解。我本身对数学也有相对较厚的兴趣,同时我也是计算机专业的学生,因此,我觉得我可参加数学建模的这个比赛。大一的暑假参加…...
什么是自动化测试?自动化测试现状怎么样?
什么是自动化测试:其实自动化测试,就是让我们写一段程序去测试另一段程序是否正常的过程,自动化测试可以更加省力的替代一部分的手动操作。 现在自动化测试的现状,也是所有学习者关心的,但现在国内公司主要是以功能测…...
CHAPTER 2 Web HA集群部署 - Heartbeat
Web HA集群部署 - Heartbeat1. Heartbeat 概述1.1 Heartbeat主要组成部分2. 环境依赖2.1 环境及组件软件2.2 关闭firewalld & selinux2.3 配置双机互信,SSH密钥登录2.4 同步时间(以主节点时间为准)2.5 配置域名解析3 安装软件3.1 安装…...
蓝桥杯每日一题:不同路径数(dfs深度优先)
给定一个 nm的二维矩阵,其中的每个元素都是一个 [1,9] 之间的正整数。 从矩阵中的任意位置出发,每次可以沿上下左右四个方向前进一步,走过的位置可以重复走。 走了 k 次后,经过的元素会构成一个 (k1) 位数。 请求出一共可以走出…...
NCRE计算机等级考试Python真题(十)
第十套试题1、数据库系统的核心是___________。A.数据库管理系统B.数据模型C.软件工具D.数据库正确答案: A2、下列叙述中正确的是___________。A.线性表链式存储结构的存储空间可以是连续的,也可以是不连续的B.线性表链式存储结构与顺序存储结构的存储空…...
【蓝桥杯嵌入式】点亮LED灯,流水灯的原理图解析与代码实现——STM32
🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都在这儿哦,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 - 蓝…...
RK3288-android8-es7210-阵列麦克风
ES7210驱动包 应需求调试一个ES7210的阵列麦克风 首先移植 From 234647c69a57c32198c65836e7fc521dc22e444b Mon Sep 17 00:00:00 2001 From: LuoXiaoTan <lxt@rock-chips.com> Date: Tue, 10 Jul 2018 18:08:50 -0700 Subject: [PATCH] ASoC: codecs: add es7210 adc …...
硬件工程师常见问题与答疑
在工作中,尤其是做了很多年的,有些问题可能不知道,又不好意思问,怕别人说你连这个都不知道?很尴尬,而且百度又搜不到,本博主收集了很多答疑,希望里面有对你有用的,或者是…...
【Java】Java进阶学习笔记(一)—— 面向对象(封装)
【Java】Java进阶学习笔记(一)—— 面向对象(封装)一、类中成分1、类中成分2、this关键字this() 访问构造器方法3、static关键字1. 成员变量的区分2. 成员方法的区分3. 成员变量访问语法的区分二、封装1、封装的定义封装的好处2、…...
jsp拆迁管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 JSP 拆迁管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&…...
CCNP350-401学习笔记(易错题合集)
CCNP350-401学习笔记(1-50题)_殊彦_sy的博客-CSDN博客CCNP350-401学习笔记(2023.2.17)https://blog.csdn.net/shuyan1115/article/details/129088574?spm1001.2014.3001.5502CCNP350-401学习笔记(51-100题)…...
喀秋莎Camtasia2023最新版本电脑录屏剪辑软件
录屏软件的鼻祖是techSmith 的喀秋莎(Techsmith Camtasia Studio),视频编辑软件Camtasia 2023发布,十大新功能放出!作为一个自媒体人,每天都要录制编辑视频,选择一个好的视频编辑工具就是大家首先面临的一个…...
「考研算法」
考研算法 前言 本系列文章涉及的算法内容,针对的是哈尔滨工业大学854科目。在本文中通过具体的算法题进行讲解相应算法。 今天涉及的算法主要有线性筛,十大排序中快速排序和归并排序。 后续会有动态规划的相关算法以及尝试模型的总结,如果…...
Android Framework-操作系统基础
最近在看《深入理解Android内核设计思想(第2版)》,个人感觉很不错,内容很多,现将书里个人认为比较重要的内容摘录一下,方便后期随时翻看。 计算机体系结构 硬件是软件的基石,所有的软件功能最…...
美国最新调查显示 50% 企业已在用 ChatGPT,其中 48% 已让其代替员工,你怎么看?
美国企业开始使用ChatGPT,我认为这不是什么新闻。 如果美国的企业现在还不使用ChatGPT,那才是个大新闻。 据新闻源显示,已经使用chatGPT的企业中,48%已经让其代替员工工作。 ChatGPT的具体职责包括:客服、代码编写、招…...
[Java·算法·中等]LeetCode17. 电话号码的字母组合
每天一题,防止痴呆题目示例分析思路1题解1分析思路2题解2题目 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。…...
C#7/C#8/C#9 与dotnetSDK 以及dotnet framework对应关系
语言版本 对应的.net framework版本 对应的.net sdk版本 推荐使用的vs studio C#7.3 3.5、 4.0、 4.5 、4.5.1、 4.5.2 、4.6 、4.6.1、 4.6.2 4.7.1、 4.7.2 .netcore 2.0、.netcore2.1、 .netcore2.2 C#8.0 / F#4.7 不支持 .netcore 3.0、.netcore 3.1 C# 9.0 …...
jvm调优经验总结
最近一段时间很忙,忙到每天10点多11点下班还是感觉有很多事没有做完,不过倒也没有什么太过低落的情绪,有时候只安静的看一个视频,简单看点文字,或者平静的坐着,并没有太多想法。短时间的工作压力是可以接受…...
等保合规知识常见问题解答
Q1:什么是等级保护? 答:等级保护是指对国家重要信息、法人和其他组织及公民的专有信息以及公开信息和存储、传输、处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的信息安全产品实行按等级管理,对信息系统…...
分享5款Windows同类软件中的翘楚
今天要给大家推荐的是5款软件,每个都是同类软件中的个中翘楚,请大家给我高调地使用起来,不用替我藏着掖着。1.沙盒工具——Sandboxie Sandboxie是一个电脑必备的沙盘工具,对于从网上下载的软件安装包、文件、视频、图片等等一切不…...
个人网站简单/个人免费网站建设
临近年底,人们日益关注格力董事长董明珠与小米董事长雷军的10亿赌约谁将赢的问题,其实当下对格力最不利的是它的直接竞争对手美的正凭借多元化的优势在利润方面快速缩短与格力的差距,而此前在营收方面前者已将后者甩开一大截距离,…...
WordPress自定义json接口/肇庆seo优化
日志统计 #尺取法 #vector容器 #全局变量能开更大的空间哦~ 题目 小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞"。 现在小明想统计有哪…...
网站关键词优化方式/知乎推广优化
本文主要分为上下两部分,(上)部分主要介绍一下企业内部什么时候需要引入AI技术(这里的AI技术泛指机器学习、深度学习、NLP、视觉、语音、推荐等),(下)部分主要介绍一下在引入这些AI技…...
哪个网站名片做的号/网站seo方案
随机生成姓名 public function getChar($num2) // $num为生成汉字的数量{$first array(赵,钱,孙,李,周,吴,郑,王,冯,陈,褚,卫,蒋,沈,韩,杨,朱,秦,尤,许,何,吕,施,张,孔,曹,严,华,金,魏,陶,姜,戚,谢,邹,喻,柏,水,窦,章,云,苏,潘,葛,奚,范,彭,郎,鲁,韦,昌,马,苗,凤,花,方,任,袁…...
室内设计公司取名字大全集/长春seo技术
文章目录一:无约束条件二:等式约束条件--拉格朗日乘子2.1拉格朗日乘子法的定义以及推导2.2一个简单的例子:引入: 优化问题通常是指对于给定的某一函数,求其在指定作用域上的全局最小值(因为最小值与最大值可以很容易转…...
城乡建设部注册建筑师网站/最吸引人的营销广告词
Visual C#读取Excel表格中的数据: 一.程序设计及运行环境 (1).微软视窗2000 服务器版 (2)..Net Framework SDK Beta 2 (3&…...