音视频之H.265/HEVC编解码并处理
H.265/HEVC系列文章:
1、音视频之H.265/HEVC编码框架及编码视频格式
2、音视频之H.265码流分析及解析
3、音视频之H.265/HEVC预测编码
4、音视频之H.265/HEVC变换编码
5、音视频之H.265/HEVC量化
6、音视频之H.265/HEVC环路后处理
7、音视频之H.265/HEVC熵编码
8、音视频之H.265/HEVC网络适配层
9、音视频之H.265/HEVC编解码并处理
新一代视频压缩标准 H.265/HEVC 在很大程度上是为了满足人们对于高分辨率视频的需求,而对于高清乃至超高清视频,分辨率达到了4kx2k或8kx4k,无论是从编码还是从解码的角度,其计算复杂度都是极高的。而为了提高H.265/HEVC的网络适应能力,其压缩性能与H.264/AVC 相比显著提高,相同条件下的码率可以降低50%,获得性能提升的代价就是编解码复杂度的大大提高。
与H.264/AVC相比,H.265/HEVC的复杂度主要体现在以下几点:H.265/HEVC 的帧内预测模式增多,H.265/HEVC中包含角度预测、DC预测、平面预测等35 种预测模式,远远超过了H.264/AVC 的 17 种模式使得模式选择的复杂度大大增加:H.265/HEVC的区域划分方式更加多样化,提出了树形划分结构,划分的单元大小更加多种多样,出现了非对称划分,运动补偿更加复杂;H.265/HEVC中增加了变换单元的概念,最大变换单元的大小由H.264/AVC中的8x8增大到现在的32x32,运算量更是不可同日而语。H.265/HEVC 标准下的编解码器,其复杂度将可能超过以前编解码器数十倍。
H.265/HEVC 对处理器的计算能力以及实时编解码都提出了很大的挑战,如此高的运算复杂度不能仅仅依赖于处理器计算能力的提升,在实际情况下,高性能处理器的成本是非常高昂的。随着处理器多核架构的发展,在多核环境下并行处理可以成倍地增加编解码速度,成为一种有效的解决方式。
一、视频编解码并行处理技术:
1、并行处理基本概念:
并行处理一般是指许多指令得以同时进行的处理模式。并行处理通常是将处理的过程分解成小部分,之后采用多个运算单元以并发方式加以解决。本章只讨论使用多个处理器的并行处理技术,其通常分为两种:功能并行和数据并行。下面结合视频编解码原理对这两种并行方式做简要介绍。
功能并行:
功能并行是指将应用程序划分成相互独立的功能模块,每个模块间可以并行地执行。这种并行方式也被称为流水线型并行,是将各个独立的模块划分给不同的运算单元,各个模块之间通过流的方式来进行数据交换和通信,最终再将各个单元串接在一起。功能并行充分利用了时间上的并行性来获得加速的效果,比较适用于硬件实现。
在视频编解码中,我们可以将编解码器划分为各个不同的模块,以解码为例,如图10.1(a)所示,各个模块映射到不同的运算单元,各自独立执行,完成不同的功能。由前面几章可以知道,H.265/HEVC的解码过程分为熵解码、反量化、反变换、帧内预测、帧间预测、去方块滤波和样点自适应补偿等。我们根据这些模块的相互联系和运作机制,可以对它们进行重新划分组合,从而实现功能并行。
功能并行的缺点也是很明显的。由于分配给不同运算单元的功能模块是不同的,因此很容易产生载荷失衡问题,有的运算单元的负载较轻,处理速度较快,而有的运算单元的负载较重,处理速度慢,总体上整个程序的运行效率就会降低。功能并行还需要在不同运算单元间进行数据通信,当数据量较大时,需要花费额外的资源来进行存储。另外,功能并行的扩展性较差,由于划分好的模块已经分配给不同的运算单元,在增加或减少运算单元时,需要对原有的模块进行重新划分和分配。
数据并行:
数据并行是将数据信息划分为相互独立的部分,每一部分交给不同的运算单元来执行,从而实现并行处理。这种方式下,不同运算单元上执行的程序是相同的,而且处理的是相互独立的数据信息,因此不需要进行运算单元间的通信,如图10.1(b)所示。
H.265/HEVC 中提供了适于进行数据并行处理的结构单元,如片和Tile,在不同的片和Tile中,数据信息是相互独立的,这样有利于将其分配给不同的运算单元来处理。对于比片和Tile小的划分单元,H.265/HEVC支持波前并行处理(Wavefront Parallel Processing,WPP),这是对于相互具有依赖关系的图像单元进行数据并行处理的方法。针对这种情况,需要通过适当的核间通信来消除数据单元之间的依赖关系,从而使得具有依赖关系的数据单元可以在不同的运算单元中进行处理。
对于数据并行,当数据块数目多于运算单元数目时,各个运算单元均处于持续运行状态,比较容易达到负载均衡。另外,数据并行具有非常好的扩展性,易于软件实现,当数据单元数目增多时,可以很容易地增加运算单元的数目来提升并行速率。
2、H.265/HEVC编解码并行处理方式:
考虑到 H.265/HEVC 标准的特点,在解码过程中,解码在Slice、Tile 以及 CTB行的起始处都有可能进行概率模型初始化,而对于不同的图像,初始化的位置都不相同。由于熵解码的依赖关系与后续解码模块的依赖关系不一致,如果在并行过程中不加以区分,会给整个并行解码带来很多麻烦,解码效率大大降低。因此H.265/HEVC的解码过程可以分成两个串行的功能模块,即熵解码和并行解码两部分,熵解码部分主要进行熵解码,而并行解码部分主要进行预测、反变换、反量化和去方块滤波等。两个功能模块组成串行的一级流水线,而分别在两个模块内部,针对不同的子数据块进行数据并行。这样一来,H.265/HEVC并行解码模型混合了功能并行和数据并行两种方式。H.265/HEVC解码器混合并行模型如图 10.2所示。
解码器中功能模块间的并行与通用的功能并行相似,而数据并行需要根据视频编码的特点考虑编码单元间的数据依赖关系。这里主要介绍H.265/HEVC 编解码器的数据并行技术,包括基于 Tile 的并行和波前并行两种方式。在进行基于 Tile 的并行时,由于Tile 的相互独立性,不需要考虑它们之间的相互依赖关系,而在进行波前并行处理时,数据间的相互依赖关系就显得尤为重要了。
3、 H.265/HEVC 编码单元数据依赖关系
针对并行处理的编码单元,必须消除数据间依赖关系的影响。如波前并行处理过程中所用到的数据块并不是相互独立的,它们之间存在相互参考的关系,在并行解码过程中,解码当前块所需要参考的数据仍未解码,那么当前块的解码也就无法展开,因此,波前并行处理必须在满足各个数据单元(CTB)之间依赖关系的前提下进行。
H.265/HEVC 编码单元的数据依赖关系主要由帧内预测、帧间预测、去方块滤波以及样点自适应补偿产生,其具体依赖关系如下。
- 帧内预测:当前CTB有可能会依赖左方、左上方、上方、右上方的 CTB 的像素信息和模式信息。
- 帧间预测:当前CTB块的运动矢量有可能会需要由左方、左上方、上方、右上方的CTB预测得到。如图10.3(a)所示,对于帧内预测和帧间预测部分,要进行并行处理,需要在解码当前CTB块时保证左方、左上方、上方、右上方的 CTB 块已经解码完成。而对于去方块滤波需要保证左方和上方的块已经解码完成。
- 去方块滤波:对当前CTB块进行边界滤波的过程中需要参考左方CTB块的左侧四列像素、上方CTB块的底部四行像素对边界进行分析。如图10.3(b)所示,在对图中垂直边界滤波时,需要保证左方的块已经解码完成,而在对图中水平边界滤波时,需要保证边界上方的块已经解码完成。
- 样点自适应补偿(SAO):SAO 的边缘补偿有0°、45°、90°、135°四种情况,因此对当前CTB块进行补偿时,其周围的8个块都有可能被参考,依赖关系较为复杂。如图10.3(c)所示,以135° SAO为例,对当前CTB左上角的像素进行样点自适应补偿时,需要参考左上方CTB右下角的像素值。
二、H.265/HEVC标准中并行处理新技术:
H.265/HEVC标准中增加了很多新的特性和句法结构用以实现并行处理,如 Tile、依赖片、波前并行处理等,使得并行处理成为H.265/HEVC的重要特征。
1、Tile:
Tile 是 H.265/HEVC 中新增加的数据单元,它将原图像划分为一个个独立的矩形区域,各个矩形区域独立进行编码,不会进行相互参考。Tile的引入主要是为了进行并行处理,而非同步和纠错。Tile改变了原本图像中CTB的扫描顺序,Tile中的CTB是根据光栅扫描顺序进行扫描的,而这些 Tile 也是根据光栅扫描顺序扫描的。如图10.4所示,第一个 Tile中的12个CTB是按照光栅扫描顺序扫描的,而第二个Tile也按照光栅扫描顺序排列在第一个 Tile 后面。
类似于 Slice,不同的 Tile 之间是相互独立的,但与 Slice 相比,Tile具有更好的编码效率。因为从划分方式上来看,Tile所包含的像素与Slice包含的像素相比具有更高的相关性。如图10.5(a)所示,Slice一般横向跨度较大,而且并不一定是规则的,同一个Slice 中的块之间的空间距离可能会很大,相关性较低。如图10.5(b)所示,Tile的划分比Slice要规则,块与块之间的空间跨度一般不会很大,相关性较强。从空间结构上来看,一个Slice可能会包含多个Tile,一个Tile也可能会包含多个Slice,但绝对不会出现一个 Slice 跨越 Tile 边界的情况,同样也不会出现一个Tile跨越 Slice 边界的情况。当多个Tile位于同一个Slice 当中时它们可以共用同一个 Slice 头,从而可以节省码率。
Tile 的引入减少了由于运动预测所需要的缓冲数量。通常来说,在对当前CTB进行帧间预测时,需要为运动补偿存储相应的参考信息。这些数据会一直存在于解码器缓存中,直到需要参考它的区域解码完成。如图10.6所示,在引入Tile之前,由于光栅扫描的原因,解码器按顺序解码,当前CTB所需要的参考块之前的CTB块都需要依次进行存储,所需要存储的像素点数为PicWx(2xSRy+CTBH-1)+2xSRx。其中PicW为图像宽度,CTBH为CTB的高度,SRx为最大水平运动失量,SRy为最大垂直运动矢量。而在引入Tile 之后,由于Tile改变了原有的光栅扫描顺序,很多原本需要依次存储的CTB现在不需要存储了,现在运动估计所需要存储的像素点数大约为(TileW+2xSRx)x(2xSRy+CTBH)其中 TileW为 Tile单元的宽度。大多数情况下,(TileW+2xSRx)要小于PicW,尤其是对于高清视频序列。
Tile的引入不是没有代价的。类似于Slice,率失真性能会随着Tile数目的增加而降低。因为Tile单元的划分使得 Tile 边界附近信息的相关性被破坏了,而且CABAC编码也会在Tile边界处进行概率型的更新,这些都降低了 H.265/HEVC 的编码效率。
2、波前并行处理:
Slice 和 Tile 都有利于H.265/HEVC 并行的实现,但是这两种数据结构都破坏了图像原有的在Slice和Tile边界上的相关性,造成了一定的性能下降。H.265/HEVC引入了波前并行处理算法,它允许多行CTB可以同时进行处理,但是后一行的处理要比前一行滞后两个CTB,这样可以在不破坏正常相关性的前提下进行并行解码,保证了原始性能。
在正常的解码顺序下,每一幅图像或者Slice的CTB是按照光栅扫描顺序从左到右,从上到下进行的。在波前并行处理中,需要将不同的CTB 行放入不同的运算单元进行处理,因此需要对不同核中CTB的编码顺序进行协调。如图10.7所示,根据 H.265/HEVC的数据依赖关系可知,在 CTB(1,3)解码完成后,CTB(2,2)所需的依赖信息都已经解码完成,同理,在 CTB(2,1)解码完成后,CTB(3,0)所需的解码信息也都已经解码完成。因此 CTB(1,4)、CTB(2,2)和CTB(3,0)3个CTB块可以分别交给3个不同的运算单元同时进行解码。以上就是波前并行处理的主要方法,在该方法中,原本的光栅扫描顺序没有改变,CTB的相互依赖关系也得以保留,只是由于并行处理,不同行的CTB的解码顺序有所改变。
同时H.265/HEVC中还加入了entropy_coding_sync_enabled_flag这语法元素,当其值为1时,CABAC编码会在每一行的开头处进行概率模型的更新,这样一来,CABAC熵解码也可以使用波前并行算法进行实现。但是当其值为0时,CABAC熵编码只能在Slice和Tile的边界处进行更新,由于不同 CTB行的前后依赖关系,此时的CABAC解码不能采用波前并行处理。
3、依赖片:
H.265/HEVC中增加了依赖片这一数据单元,它将一个完整的Slice划分为不同的区域,分别封装到不同的独立NAL单元当中,而这些区域有可能是相互关联的。依赖片的引入同样有利于并行处理的实现,尤其是在解码端。片通常是相互独立的数据单元,而依赖片则允许是相互参考的。在划分的时候,可以将一段用于波前并行处理的CTB行数据或一个 Tile 打包到一个单独的NAL单元当中,这样一个单元被称为一个依赖片。如图10.8所示,若采用波前并行处理算法,图中的4行CTB都可以分别交给不同的运算单元进行处理,就可以将它们分别封装到4个不同的NAL单元当中。由于依赖片会参考其他片,如图中的NAL2,其中的数据会参考NAL1中的数据,它们具有一定的依赖性,所以要解码当前依赖片必须等待其参考的片先进行解码,但不用全部解码完,只需要参考片完成部分解码,当前依赖片的解码便可以开始,这与波前并行处理算法是很相似的。
在并行结构上来看,这样做对于并行速率并没有什么改变,可能还会因为NAL单元数的增多使得编码效率下降。但是从网络传输方面考虑依赖片降低了NAL单元的大小,利用依赖片进行并行处理可以有效减少解码时延。
三、 H.265/HEVC编解码并行策略:
视频序列是由一个或多个图像组GOP组成的,GOP通常被用来进行视频同步,它们是相互独立的,没有任何相关性。每个GOP包含多幅图像,图像根据其特点又可以分为I图像、P图像和B图像。从图像级向下划分又可以分为Slice 和Tile,Slice 和 Tile 作为两种划分单元可以将一幅图像划分为一个个相互独立的图像单元,而Slice和Tile都是由多个CTB组成的。最后,每个CTB又包含了多个像素。从H.265/HEVC的数据结构来看,在每一个层级上都可以进行并行处理,每一个层级上的并行都有其各自的优缺点和并行策略。接下来我们将对这些不同层级上的并行策略进行讨论和分析。
1、GOP级并行:
在H.265/HEVC中GOP级的并行是可行的。我们可以将一个视频序列中的不同GOP交给不同的运算单元来并行处理。如图10.9所示,线程T1、T2和T3分别对GOP1、GOP2和GOP3 进行并行处理,T0 负责统筹控制。当某个线程完成对其当前GOP的处理后发送请求至T0,T0会根据各线程的完成情况为其分配下一个GOP,这样的并行过程持续到整个视频序列的结束。
GOP的数据量是庞大的,因此GOP级的并行要求每个运算单元都有较多的存储资源。如果这些运算单元使用的是公共缓存,那么GOP级的并行将会变得十分低效,因为大量数据的频繁读入与读取是非常耗费时间和资源的。另外,GOP级并行较之其他并行方式,其解码时延是较高的,因此这种并行方式更适用于编码端。
2、图像级并行:
在图像级数据结构中,由于运动预测的存在,不同的图像之间会有时域上的依赖性,但这种依赖性并非是不可避免的。一个视频序列中通常包含I、P、B 3种数据图像,如图10.10所示,由于I图像和P图像都有可能会用作参考,后续图像要进行解码必须等待它们的解码完成,因此通常对这些图像不做并行考虑。
对于B图像,图中将B图像分成了3个等级、
和
;,其中
会用作
和
的参考图像,而
会作为
的参考图像,但是同级的B图像之间不会相互参考,高级的B图像也不会作为低级B图像的参考图像,更不会作为I图像和P图像的参考图像,这就意味着同级的B图像之间是相互独立的。这就为图像级的并行处理提供了可能,我们可以将同级的B图像分别交给不同的运算单元来进行处理,当然前提是更低级的B图像已经解码完成,当前级别B图像解码的先决条件已经满足。
这样的实现方式十分受限于B图像的数量,当P图像之间的B图像数目较少时,可以并行的线程数目也就很少,影响了并行的效率。另外,由于B图像也会被用做参考,不同级别的B图像之间不能进行并行解码,并行只能在同级 B图像之间进行,这在更大程度上限制了并行的效率。
3、Slice级并行:
虽然 Slice 通常被用来实现数据同步、差错控制和随机接入等功能,但是由于Slice的相互独立性,Slice级的并行处理是可行的。而且在H.265/HEVC中,CABAC编码在每个Slice的结尾都会对上下文模型进行更新,这就允许不同的 Slice 的熵编码部分并行进行。除了编码部分,不同的 Slice 数据也可以被送给不同的运算单元进行处理而不用考虑它们的相关性。如图10.11所示,图像中存在3个相互独立的Slice,分别送给3个运算单元来进行并行处理。
Slice 级并行的缺点是比较明显的。第一,由于每幅图像的 Slice 数目是由编码器决定的,在解码端,并行的数量是难以确定的;第二,虽然Slice是完全独立的,但在进行去方块滤波时,有可能会跨越Slice的边界,这降低了并行的扩展性;第三,由于Slice的内容可能会相差较大,这会引起并行过程中的负载失衡问题;第四,也是最重要的,当Slice数目较多时,Slice级并行可能会造成码率成倍增加,这在很多实际的码流环境下是不允许的。
4、Tile级并行:
Tile 将图像划分为一个个独立的矩形CTB组。Tile 的数量以及它们的位置和大小通常会随图像的变化而变化。对于熵解码和预测,不同的Tile 数据是相互独立的,而且CABAC熵解码也会在每个Tile 的结尾进行上下文模型的更新,这些都有利于实现Tile 级并行。但是去方块滤波和样点自适应补偿仍然有可能会跨Tile边界进行,需要额外的处理来消除这种操作所造成的 Tile 间的依赖性。
Tile 改变了原有的CTB的扫描顺序,CTB的光栅扫描顺序会受到Tile边界的约束,这样的数据结构不利于在单核上实现 H.265/HEVC 的编/解码过程,但有利于多核并行处理的实现。
由于 Tile 间的独立性,Tile 级通常将整个 Tile 分配给一个运算单元,因此不需要 CTB级的核间通信,但是如果去方块滤波跨越 Tile 边界进行,就需要进行核间通信来消除Tile间的依赖性。如图10.12所示,假设图中有左右两个 Tile,将这两个 Tile 分别交给两个不同的运算单元进行并行处理。由于去方块滤波跨越Tile边界进行,那么在滤除中间那条垂直的边界时会出现右边 Tile 参考左边Tile的情况。这时我们需要进行核间通信,来协调两个运算单元的解码进程。比如,当右边Tile 解码到第 21个CTB时需要查看左边Tile的第8个CTB是否解码完成,只有当第8个CTB解码完成后,第21个CTB才能继续进行解码。通常情况下这种核间通信是有必要的,因为如果不跨越Tile 边界进行去方块滤波,就有可能会造成视觉上的块效应。
Tile 级并行同样具有一些 Slice 级并行的缺点。由于 Tile 单元内容的差异性,负载失衡的问题仍然有可能会发生。而且,当并行处理的Tile数目较多时,码率飙升问题仍然是不可避免的。
5、CTB级并行:
H.265/HEVC中采用了波前并行处理(WPP)算法来进行CTB级的并行。另外,对于CABAC熵解码,当entropy_coding_sync_enabled_flag为1时,CABAC上下文模型会在每一行的结尾处进行更新,这使得编码和熵解码的 CTB 级并行成为可能。当进行波前并行处理时,多行CTB被分别送到不同的运算单元中进行处理,但是由于相邻CTB之间的依赖性,这些运算单元不能同时开始运行。除解码第一行CTB的线程外,每一个线程都要比上一个线程落后两个CTB进行解码,这也就意味着所有的运算单元不可能同时结束。这会造成并行效率的降低,尤其是当运算单元数较多时更为明显。
尽管在线程数较多时,CTB级并行的效率有所降低,但CTB级并行处理相对于其他并行方式还是有很多优点的。首先,CTB级并行有较好的扩展性。随着图像分辨率的增加,CTB级并行的线程数也可以很方便地增加。其次,相对于其他层级的并行方式,CTB级并行可以更好地实现负载均衡。由于分配给各个运算单元的数据信息量是较少的,因此各运算单元的运算时间不会有太大差异,因此很容易实现负载均衡。
然而CTB级的并行也存在一些缺点。首先是解码的上下文模型更新问题。在进行熵解码之前,CTB单元是无法区分的,因此必须先进行熵解码,再进行之后的图像处理。但是CABAC解码的概率模型需要参考从上一个更新点以后所有的码流信息,而我们无法保证在每一行CTB的开头都有一个更新点。这样波前并行处理算法就无法在CABAC熵解码部分实现,我们只能分别进行熵解码和并行处理。根据CABAC上下文模型的更新位置,我们可以确定CTB级并行的起始位置。如果CABAC上下文模型在Slice开头处更新,那么我们就可以将该Slice送入并行过程。该Slice的不同CTB行被交给不同的运算单元,利用波前并行处理算法进行解码,直到该Slice的解码结束。
其次是CTB级并行无法保证输出码率的稳定性。根据波前并行处理算法,在并行处理开始时,满足依赖关系可以进行解码的CTB数目是较少的,码率较低。随着解码的进行,越来越多的运算单元启动,码率开始增大,直到达到最大值。在解码达到尾声时,解码运算单元又会逐个终止,这样码率又会逐渐减少到零。这样一来,CTB级并行处理就无法达到恒定的码率,而且还会造成并行效率的下降。
针对上述问题,人们提出了一种叫作重叠波前并行的方法,来减少并行过程中由于线程数增加和减少所带来的并行效率的下降。在最初的波前并行算法当中,如果一个运算单元处理完一行CTB之后,在当前图像中没有剩余的 CTB行可以交给它进行处理,如图10.13中的线程T4,那么在整幅图像解码完成之前,该运算单元会一直处于等待状态。之后,对于下一幅图像,波前并行算法会重新开始。而在重叠波前并行算法中,在图像的运动矢量足够小的情况下,一个运算单元处理完一行CTB之后,如果当前图像中没有剩余的CTB行可以交给它进行处理,该运算单元可以直接开始对下一幅图像的处理而不用等待整幅图像解码的完成。如图10.13所示,共有6个运算单元来对当前图像进行波前并行处理,当线程T4完成对分配给它的CTB行的解码后,会发现在当前图像中已没有满足条件可以分配给它,于是线程 T4直接转入下幅图像进行解码。但是该算法的前提是运动矢量要足够小,对于前一幅图像,前4行CTB是解码完成了的,因此它们可以作为后幅图像的参考,后幅图像的最大运动矢量不能超出这4行CTB的范围,否则可能会导致后幅图像解码时缺少参考信息。重叠波前并行处理不能完全使得并行解码时的线程数恒定,但它可以较为有效地解决由于线程数增加和减少所带来的并行效率下降问题。
从数据结构上来看,CTB 级并行和Tile 级并行是可以同时实现的,如图10.14所示,可以将一幅图像划分为4个Tile,每个 Tile 交给一组运算单元来处理,而每组运算单元按照CTB级并行的方式可以并行处理3行CTB,这在理论上来说比单纯进行CTB级并行或Tile级并行效率要高。但是同时实现将会造成线程数大幅增加,复杂度和码率都会急剧上升。过多的运算单元之间进行通信将会占用较多的资源,而且,就每个运算单元来看,其所分到的数据信息量将会很少,负载均衡难以实现,利用率降低。因此H.265/HEVC中没有提出CTB级和Tile 级同时并行的方案。
参考资料:
《新一代高效视频编码 H.265/HEVC 原理、标准与实现》——万帅 杨付正 编著
相关文章:
音视频之H.265/HEVC编解码并处理
H.265/HEVC系列文章: 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 4、音视频之H.265/HEVC变换编码 5、音视频之H.265/HEVC量化 6、音视频之H.265/HEVC环路后处理 7、音视频之H.265/HEVC熵编…...
Python入门(一)
目录 一、Python数据类型 1.字面量 2.注释 3.变量 4.数据类型 二、 运算符 1.数据类型之间的相互转换 2 算数运算符 3、逻辑运算符 三、判断语句 if 四、循环 1、while循环 2、for循环 2.1 for...else... 五、格式化字符串 1.字符串 1.1创建字符串的方式&…...
2025年01月09日德美医疗前端面试
目录 vue2 的双向绑定的原理vue3 的双向绑定原理vue 的生命周期vue 子组件为何不能修改父组件的值js delete 删除数组的某一个值会怎么样vue 和 react 的 diff 算法什么是闭包原型链this指向 vue2 的双向绑定的原理 以下是 Vue 2 双向绑定的原理: 1. 核心概念 …...
02 mysql 管理(Windows版)
一、启动及关闭 MySQL 服务器 1.1 通过 “服务” 管理工具 winr打开运行,输入services.msc 找到MySQL80,这个是我们在安装mysql的时候给的服务的名称,具体见文章mysql 安装 右键选择启动或者停止。 1.2 通过命令提示符 1.2.1 关闭命令…...
开发搭载OneNet平台的物联网数据收发APP的设计与实现
一、开发环境与工具准备 工具安装 下载HBuilderX开发版(推荐使用开发版以避免插件兼容性问题)安装Node.js和npm(用于依赖管理及打包)配置Android Studio(本地打包需集成离线SDK)项目初始化 创建uni-app项目,选择“默认模板”或“空白模板”安装必要的UI库(如uView或Van…...
ntdll!LdrpInitializeProcess函数分析之Peb->Ldr和全局变量ntdll!PebLdr的关系
代码部分A: PEB_LDR_DATA PebLdr; //全局变量ntdll!PebLdr NTSTATUS LdrpInitializeProcess ( IN PCONTEXT Context OPTIONAL, IN PVOID SystemDllBase ) { 代码部分B: // // Figure out process name. // Teb NtCurrentTeb…...
如何开始使用 Blender:Blender 3D 初学者指南和简介 怎么下载格式模型
Blender 是一个强大的 3D 创作套件,为动画、视觉效果、艺术等提供了一系列功能。无论您是初学者还是经验丰富的艺术家,Blender 都提供了一个免费的开源平台来释放您的创造力。凭借其内置的视频序列编辑器,Blender 还提供基本的编辑功能&#…...
Nginx安全防护与HTTPS部署
目录 一、Nginx 概述 二、Nginx 核心安全配置 (一)编译安装 Nginx (二)隐藏版本号 (三)限制危险请求方法 (四)请求限制(CC 攻击防御) (五&…...
HTTP 与 HTTPS 的深度剖析:差异、原理与应用场景
HTTP 与 HTTPS 的深度剖析:差异、原理与应用场景 在互联网的世界里,HTTP(超文本传输协议)和 HTTPS(超文本传输安全协议)是数据传输的 “高速公路”,它们承载着我们日常浏览网页、购物支付等各种…...
SMT贴片钢网精密设计与制造要点解析
内容概要 SMT贴片钢网作为电子组装工艺的核心载体,其设计与制造质量直接影响焊膏印刷精度及产品良率。本文系统梳理了钢网全生命周期中的15项关键技术指标,从材料选择、结构设计到工艺控制构建完整技术框架。核心要点涵盖激光切割精度的微米级调控、开口…...
算法每日一题 | 入门-顺序结构-三角形面积
三角形面积 题目描述 一个三角形的三边长分别是 a、b、c,那么它的面积为 p ( p − a ) ( p − b ) ( p − c ) \sqrt{p(p-a)(p-b)(p-c)} p(p−a)(p−b)(p−c) ,其中 p 1 2 ( a b c ) p\frac{1}{2}(abc) p21(abc) 。输入这三个数字,…...
Linux内核视角:线程同步与互斥的原理、实现与锁优化策略
Linux系列 文章目录 Linux系列前言一、前提知识二、线程互斥概念引入三、线程互斥3.1 什么是线程的互斥3.2 线程互斥的实现 四、锁的实现原理 前言 在前两篇文章中,我们已经对线程的相关概念及基本操作进行了深入介绍。在本篇中,我们将深入探讨编写多线…...
【区块链】Uniswap详细介绍
一、前言 本文将结合网上的资料和博主的理解,像大家详细介绍Uniswap,包括其核心概念、工作原理、版本演进、代币经济学以及风险点,适合想深入了解去中心化交易所(DEX)机制的用户。 二、Uniswap是什么 Uniswap 是一个…...
YOLOv8的Python基础--函数篇
1. 文件/目录操作相关函数 这些函数来自 os 和 shutil 模块: 函数/用法作用示例说明os.listdir(dir)列出目录下所有文件名os.listdir("./images")返回文件名列表(不包含路径)os.path.join()拼接路径os.path.join("dir"…...
vue源代码采用的设计模式分解
No.大剑师精品GIS教程推荐0地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 1Openlayers 【入门教程】 - 【源代码示例 300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3MapboxGL【入门教程】 - 【源代码图文示例150】 4Cesium 【入门教程】…...
强化学习是AI Agent的进化引擎还是技术枷锁呢?
第一章 强化学习:Agent的“灵魂”觉醒之路 1.1 AlphaGo的启示:从规则到目标驱动的范式革命 2016年AlphaGo击败李世石的事件,标志着RL首次在复杂决策场景中展现其颠覆性价值。通过深度神经网络与RL的结合,AlphaGo无需依赖人类棋谱…...
python简易实现勒索病毒
python简易实现勒索病毒 1.首先介绍Crypto库1.1首先是对称加密1.2 非对称加密1.3 哈希 2.生成RSA密钥并保存3.文件加密4.文件解密1. 导入必要的模块2. 定义解密函数3. 设置私钥的密码4. 打开并读取文件5. 导入私钥6. 读取加密数据7. 解密会话密钥8. 创建 AES 解密器9. 解密数据…...
Nacos源码—4.Nacos集群高可用分析三
大纲 6.CAP原则与Raft协议 7.Nacos实现的Raft协议是如何写入数据的 8.Nacos实现的Raft协议是如何选举Leader节点的 9.Nacos实现的Raft协议是如何同步数据的 10.Nacos如何实现Raft协议的简版总结 6.CAP原则与Raft协议 (1)CAP分别指的是什么 (2)什么是分区以及容错 (3)为…...
AWS WebRTC如何实现拉流?内部是这样实现的
当我们通过手机上的app选择某一个Iot设备,例如,摄像头,想看实时视频的时候,aws都做了什么?最近在搞自研Iot项目,借机整理一下相关流程。 App通过 AWS SDK 发起拉流请求的内部机制是AWS Kinesis Video Streams (KVS) WebRTC 模式中一个非常关键的问题。 一、KVS WebRTC …...
NGINX `ngx_http_browser_module` 深度解析与实战
1. 模块定位 ngx_http_browser_module 在 HTTP 头 User-Agent 解析的基础上,给出三个内置变量: 变量作用典型值$modern_browser当 UA 被判定为 现代浏览器 时取 modern_browser_value 指定的值;否则为空modern. / 1$ancient_browser当 UA 被…...
Elasticsearch知识汇总之 ElasticSearch高可用方案
六 ElasticSearch高可用方案 6.1 高可用架构 请求协调节点根据负载均衡,转发给主分片节点,主分片同步复制给从节点,主从节点都写入完成返回客户端请求成功。对于读请求,协调负载到任意节点数据节点,数据节点把各自符合…...
多线程2-多线程编程
引入 当我们想要代码能够实现并发执行时,我们可以使用多进程进行并发编程(在Java中并不推荐这种方式,许多API在Java标准库中都没有提供),也可以使用多线程进行并发编程(系统提供了相关的API,Ja…...
电商系统中单商户和多商户的区别
在电商的商业版图上,单商户与多商户模式如同两条并行的发展脉络,各自构建起独特的商业生态。它们在运营逻辑、商业模式等多方面存在显著差异,这些差异不仅塑造了不同的平台特性,也深刻影响着企业的发展路径。接下来,我…...
【东枫科技】代理英伟达产品:智能网卡的连接线
文章目录 总览详细:NVIDIA 400Gb/s QSFP-DD 线缆详细:NVIDIA 400Gb/s OSFP 线缆详细:NVIDIA 200Gb/s QSFP56 线缆详细:NVIDIA 100Gb/s QSFP28 线缆 总览 详细:NVIDIA 400Gb/s QSFP-DD 线缆 详细:NVIDIA 400…...
使用ip池后,爬虫还被封,是什么原因呢?
嘿,亲爱的小伙伴们!今天我们聊一个让很多爬虫工程师抓狂的问题:明明用上了IP池,结果爬虫还是被封了!怎么回事呢?如果你也曾在爬虫与反爬的“猫鼠游戏”里痛苦“翻车”,别着急,这篇文…...
C++23 新利器:深入解析栈踪迹库 (P0881R7)
文章目录 为何需要标准化的栈踪迹?P0881R7 的核心组件与使用基本用法示例与异常处理的集成优势与价值潜在的考量总结 对于 C 开发者而言,调试和错误诊断一直是开发周期中不可或缺但又充满挑战的一环。当程序崩溃或发生未预期行为时,获取清晰、…...
2025-05-06 事业-独立开发项目-记录
摘要: 2025-05-06 事业-独立开发项目-记录 独立开发项目记录 Product Hunt | InDev 独立开发者导航站https://www.producthunt.com/ Nomads.com - Best Places to Live for Digital Nomads (formerly Nomad List)https://nomads.com/ InDev 独立开发者导航站https://indev.bei…...
【Linux系统】探索进程等待与程序替换的奥秘
文章目录 前言一、重谈进程创建1.1 fork 函数1.2 写时拷贝1.3 fork 的常规用法1.4 fork 调用失败的原因1.5 创建一批进程 二、进程终止2.1 进程退出场景2.2 strerror 函数的作用2.3 errno 全局变量2.4 程序异常机制2.5 进程退出方式 三、进程等待3.1 进程等待必要性3.2 进程等待…...
Github 2025-05-06Python开源项目日报 Top10
根据Github Trendings的统计,今日(2025-05-06统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10C++项目2TypeScript项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…...
【愚公系列】《Manus极简入门》021-音乐创作助手:“音符魔术师”
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
【Azure Redis】Redis导入备份文件(RDB)失败的原因
问题描述 在测试Azure Redis的导入/导出备份文件的功能中,突然发现在Redis 4.0上导入的时候,一直报错。 image.png 问题解答 因为门户上只是显示导入失败,没有任何错误消息说明。根据常理推断,Redis 的RDB文件格式都具有一致性。居…...
git “分离头指针”(detached HEAD) 状态。
在 Git 中,当你运行 git branch 命令时,看到如下输出: * (detached from 5b596b5)master 其中的: * (detached from 5b596b5) 表示你当前处于 “分离头指针”(detached HEAD) 状态。 🧠 什…...
Gitee的介绍
目录 1.Gitee介绍: 1.1 代码托管 1.2 本土化优势 1.3 企业级服务 1.4 开源生态 1.5 多形态适配 定位:国内开发者首选的高效代码协作平台,兼顾个人开源与企业级私有开发需求。 2.Gitee和GitHub区别 3.Gitee使用教程 4.Gitee相关…...
NoUniqueKey问题和Regular join介绍
问题背景 在flink任务中,遇到了 NoUniqueKey Join的情况,导致了数据膨胀,和下游结果与数据库数据不一致问题 那NoUniqueKey Join为什么会导致问题呢,下面是其中一种场景示例: 为什么会出现 NoUniqueKey :…...
TC8:SOMEIP_ETS_027-028
SOMEIP_ETS_027: echoUINT8 目的 检查method方法echoUINT8的参数及其顺序能够被顺利地发送和接收 说白了就是检查UINT8数据类型参数在SOME/IP协议层的序列化与反序列化是否正常。 UINT8相比于测试用例SOMEIP_ETS_021: echoINT8中的SINT8数据类型来说,属于无符号整数,也就是…...
小微企业SaaS ERP管理系统,SpringBoot+Vue+ElementUI+UniAPP
小微企业的SaaS ERP管理系统,ERP系统源码,ERP管理系统源代码 一款适用于小微企业的SaaS ERP管理系统, 采用SpringBootVueElementUIUniAPP技术栈开发,让企业简单上云。 专注于小微企业的应用需求,如企业基本的进销存、询价&#…...
css filter 常用方法函数和应用实例
1. blur() 模糊 filter: blur(半径);参数:模糊半径(像素),值越大越模糊 示例:filter: blur(5px);2. brightness() 亮度 filter: brightness(百分比); 参数:1原始对比度,0全灰,>…...
chrome inspect 调试遇到的问题
1、oppp 手机打开webview 的时候, 报错这个并没有页面 Offline #V8FIG6SGLN75M7FY Pending authentication: please accept debugging session on the device. 解决方法,保持chrome 浏览器在显示的状态 去设置里开启usb 调试再关闭,反复重…...
Kotlin 中 List 和 MutableList 的区别
在 Kotlin 中,List 和 MutableList 是两种不同的集合接口,核心区别在于可变性。 Kotlin 集合框架的重要设计原则:通过接口分离只读(read - only)和可变(mutable)操作,以提高代码的安…...
openssl 生成自签名证书实现接口支持https
1.下载安装openssl Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 2.配置环境变量 将 openssl 的目录(D:\tools\openssl\bin)添加到 path 中 3.生成自签名证书 找一个存证书的目录打开powershell 3.1 生成私钥 openssl gen…...
React 中集成 Ant Design 组件库:提升开发效率与用户体验
React 中集成 Ant Design 组件库:提升开发效率与用户体验 一、为什么选择 Ant Design 组件库?二、基础引入方式三、按需引入(优化性能)四、Ant Design Charts无缝接入图标前面提到了利用Redux提供全局维护,但如果在开发时再自己手动封装组件,不仅效率不高,可能开发的组件…...
神经网络:节点、隐藏层与非线性学习
神经网络:节点、隐藏层与非线性学习 摘要: 神经网络是机器学习领域中一种强大的工具,能够通过复杂的结构学习数据中的非线性关系。本文从基础的线性模型出发,逐步深入探讨神经网络中节点和隐藏层的作用,以及它们如何…...
vue+tsc+noEmit导致打包报TS类型错误问题及解决方法
项目场景: 提示:这里简述项目相关背景: 当我们新建vue3项目,package.json文件会自动给我添加一些配置选项,这写选项基本没有问题,但是在实际操作过程中,当项目越来越复杂就会出现问题,本文给大家分享vuetscnoEmit导致打包报TS类型错误问题及…...
Ragflow服务器上部署教程
参考官方文档进行整理 克隆相应代码 git clone https://github.com/infiniflow/ragflow.git修改vm.max_map_count sudo sysctl -w vm.max_map_count262144修改 daemon.json文件 {"registry-mirrors": ["https://docker.m.daocloud.io","https://0…...
Ubuntu 系统中解决 Firefox 中文显示乱码的完整指南
Firefox 是一款流行的网络浏览器,但在 Ubuntu 系统中有时会遇到中文显示乱码的问题。本文将为您提供一个全面的解决方案,帮助您轻松解决这个烦人的问题。 问题概述 在 Ubuntu 系统中使用 Firefox 浏览器时,有时会发现中文字符显示为乱码或方块。这通常是由于缺少合适的中文…...
JVM——垃圾回收
垃圾回收 在Java虚拟机(JVM)的自动内存管理中,垃圾回收(Garbage Collection, GC)是其核心组件之一。它负责回收堆内存中不再使用的对象所占用的内存空间,以供新对象的分配使用。下面我们将深入探讨JVM中的…...
【AI News | 20250506】每日AI进展
AI Repos 1、gitsummarize GitSummarize是一个在线工具,用户只需将GitHub URL中的“hub”替换为“summarize”,即可为任何公开或私有代码库生成交互式文档。该工具利用Gemini分析代码结构,自动生成系统级架构概述、目录和文件摘要、自然语言…...
LabVIEW高冲击加速度校准系统
在国防科技领域,高 g 值加速度传感器广泛应用于先进兵器研制,如深侵彻系统、精确打击弹药及钻地弹药等。其性能指标直接影响研究结果的准确性与可靠性,因此对该传感器进行定期校准意义重大。高冲击加速度校准系统具备多方面功能,适…...
优化算法 - intro
优化问题 一般形式 minimize f ( x ) f(\mathbf{x}) f(x) subject to x ∈ C \mathbf{x} \in C x∈C 目标函数 f : R n → R f: \mathbb{R}^n \rightarrow \mathbb{R} f:Rn→R限制集合例子 C { x ∣ h 1 ( x ) 0 , . . . , h m ( x ) 0 , g 1 ( x ) ≤ 0 , . . . , g r …...
从PotPlayer到专业播放器—基于 RTSP|RTMP播放器功能、架构、工程能力的全面对比分析
从PotPlayer到专业播放器SDK:工程项目怎么选择合适的播放方案? ——基于 RTSP、RTMP 播放器功能、架构、工程能力的全面对比分析 在许多音视频项目早期,我们都听过这句话: “本地测试就用 PotPlayer 播吧,能播就行了…...