Modeling Deep Learning Accelerator Enabled GPUs

Modeling Deep Learning Accelerator Enabled GPUs 发表在 ISPASS 2019 上。文章研究了 NVIDIA 的 Volta 和 Turing 架构中张量核的设计,并提出了 Volta 中张量核的架构模型。 基于 GPGPU-Sim 实现该模型,并且支持 CUTLASS 运行。发现其性能与硬件非常吻合,与 Titan V GPU 相比,获得了99.6%的 IPC 相关性。文中还展示了 Turing 架构中张量核的操作数矩阵元素到线程的映射,并发现它们与 Volta 张量核的行为不同。

Related Work

论文的相关工作:

  • Demystifying GPU Microarchitecture through Microbenchmarking 使用广泛的微基准对 NVIDIA GT200进行了透彻的分析。他们探索了处理核和内存层次结构的架构细节。描述了先前未公开的屏障同步和内存层次结构的细节,包括 GPU 中的 TLB 组织。

  • Dissecting the NVIDIA Volta GPU Architecture via Microbenchmarking 详细研究了张量核。他们在混合精度模式下解码了 Volta 张量核的集合和步骤。

  • NVIDIA Tensor Core Programmability, Performance & Precision 研究了 Tensor Core 的精度损失和可编程性方面对 HPC 应用的影响。

  • Exploring Modern GPU Memory System Design Challenges through Accurate Modeling 研究了包括 Volta 在内的现代 GPU 的内存系统,并发现了内存系统中许多重要的设计决策。他们在 GPGPU-Sim 中对其进行建模,并在广泛的 GPGPU 工作负载上实现了非常高的相关性。

Background

Volta Microarchitecture

Volta 是 NVIDIA 第一代包含机器学习加速器的 GPU 架构。NVIDIA GPU 通常由多个流式多处理器 (Streaming Multiprocessor, SM) 组成,这些处理器通过片上网络连接到多个内存分区。 每个内存分区都包含最后一级缓存的一部分,并将 GPU 连接到片外 DRAM。 正如 NVIDIA 所描述的,每个 SM 内包含多个张量核。Volta 中的 SM 设计分为四个处理块,NVIDIA 将其称为 Sub-Core。如图 1所示,Volta 中的每个子核都有两个张量核、一个 Warp 调度器、一个调度单元和一个64KB 的寄存器文件。
在这里插入图片描述
除了新增张量核之外,Volta 还包括与机器学习工作负载性能相关的其他增强功能:

  • 每个流式多处理器 (SM) 的调度单元数量是上一代 Pascal 架构的两倍;
  • 拥有独立的整数和 32 位浮点 (FP32) 核;
  • 对发散线程,分支后面的两条路径都可以由单个 warp 内的线程以交错的方式执行。

Tensor Core

每个张量核都是一个可编程计算单元,专门用于加速机器学习工作负载。Tesla Titan V GPU 包含分布在80个 SM 中的640个张量核,每个 SM 有8个张量核,在1530 MHz 的工作频率下提供125 TFLOPS 的理论性能。根据 NVIDIA TESLA V100 GPU ARCHITECTURE,每个张量核可以在每个时钟周期完成一次 4 × 4 4\times 4 4×4 矩阵乘法累加 (MACC),即 D = A × B + C D=A\times B+C D=A×B+C,其中 A , B , C A ,B,C A,B,C 4 × 4 4\times 4 4×4 矩阵,如图 3 所示。
在这里插入图片描述

虽然单个张量核在任何时候都对 4 × 4 4 \times 4 4×4 矩阵进行操作,但 WMMA API 在更大的图块大小上公开张量核。自然地,两个 16 × 16 16 \times 16 16×16 矩阵的乘法分解为一个分块矩阵乘法,结果矩阵由十六个 4 × 4 4 \times 4 4×4 子矩阵构成,每个涉及四个 4 × 4 4 \times 4 4×4 矩阵相乘累加。因此,CUDA C++ WMMA 级别的每个mma_sync或 PTX 级别的每个 wmma.mma操作可以用64个独立的张量核操作来实现。

张量核有 FP16 和混合精度两种工作模式:

  • 在 FP16模式下,张量核读取三个 4 × 4 4 \times 4 4×4 16位浮点矩阵作为源操作数;
  • 而在混合精度模式下,它读取两个 4 × 4 4 \times 4 4×4 16位浮点矩阵以及第三个 4 × 4 4 \times 4 4×4 32位浮点累加矩阵。

Demystifying NVIDIA’s Tensor Cores

Dissecting the NVIDIA Volta GPU Architecture via Microbenchmarking 研究了列主布局中混合精度模式的矩阵操作数元素到寄存器的分布情况。文中将线程束内的一组四个连续线程称为“线程组”。

为了描述方便,论文余下部分中将其缩写为 threadgroup。由于一个 warp 中有32个线程,因此一个线程束中有 8 8 8threadgroup。给定线程的 threadgroup id(类似于 Dissecting the NVIDIA Volta GPU Architecture via Microbenchmarking 中的“group id”)根据 ⌊ t h r e a d I d x 4 ⌋ \lfloor\frac{threadIdx}{4}\rfloor 4threadIdx 得到。

Microbenchmarks

本节讨论了用于分析张量核实现的微基准测试。其包含两种类型的微基准测试:

  • 一种旨在确定数据如何移入和移出张量核;
  • 另一种用于确定张量核执行操作所需的时间。
Fragment to thread mapping

图 4包含 III-B 节中使用的 CUDA 代码的一部分,用于确定操作数矩阵元素和线程之间的映射。此代码是在 16 × 16 16\times16 16×16 矩阵上运行的更大的通用矩阵乘法 (GEMM) 内核的一部分。每个线程加载输入矩阵的一个段并将其打印到输出控制台。通过使用不同的值初始化输入矩阵的每个元素,可以直接揭示从操作数矩阵元素到线程束内线程的映射。
在这里插入图片描述

Analyzing machine instructions

正如在 III-C. Machine ISA interface 节中详细描述的那样,PTX 指令被映射为多个HMMA SASS 指令。图 5 在高层次上说明了用微基准测试分析HMMA指令如何访问数据时的操作。作者使用 radare2 将HMMA操作替换为“无操作” ( NOP) 指令的操作,仅保留一个HMMA操作。
在这里插入图片描述

图 6 概括地说明了微基准测试用于分析张量核心上低级操作的时序的方法。为了开发这些微基准测试,作者使用 radare2 添加了在 1 s t 1^{st} 1st 之前和 n t h n^{th} nth HMMA指令之后读取时钟寄存器的代码。
在这里插入图片描述

Operand matrix element mapping

本节总结了矩阵元素到线程的分布的分析结果。

Volta Tensor Cores

图 7a 和 7b 总结了矩阵操作数的元素如何映射到线程束内各个线程的寄存器。

  • 大矩形 ( 1 ◯ \textcircled{1} 1) 表示 FP16和混合精度操作模式的 16 × 16 16\times16 16×16 操作数矩阵 A 或 B。
  • 较小的方块是操作数矩阵中的各个元素,同一行中的元素在内存中连续存储。
  • 每个 threadgroup 加载一个不同的 4 × 16 4\times16 4×16 子矩阵,文中将其称为一个段。组成操作数矩阵的四个段用不同的着色突出显示。

在这里插入图片描述
图 7a 的右上部分 ( 2 ◯ , 3 ◯ \textcircled{2},\textcircled{3} 2,3) 显示了段内的元素如何分布在一个线程组的线程中。在 Volta 上,每个段都由两个不同的 threadgroup 加载。因此,A 和 B 操作数矩阵的每个元素 由 Volta 上的线程束中的两个不同线程加载。图 7a 的底部部分 ( 4 ◯ \textcircled{4} 4) 与左上角部分 ( 1 ◯ \textcircled{1} 1) 相结合,总结了确切的映射。例如,实验发现操作数矩阵 A 的连续前四行由 threadgroup 0和2加载。

以行优先布局存储的操作数矩阵 A 的矩阵元素到线程的分布与以列优先布局存储的操作数矩阵 B 的分布相同,反之亦然。

  • 对于行主布局中的操作数矩阵 A,threadgroup 内的每个线程使用两个合并的 128 位宽加载指令,加载一行中的 16 16 16 个连续元素 ( 2 ◯ \textcircled{2} 2);
  • 而在列主布局中为了加载4行, threadgroup 内的每个线程通过四个合并的 64 位宽加载指令加载四个块,每个块内四个连续元素,每个加载指令的跨距为 64 个元素 ( 3 ◯ \textcircled{3} 3)。

如图 7b 所示,对于操作数矩阵 C,矩阵元素到线程的分布是不同的。具体来说,

  • 对于操作数矩阵 C,每个 threadgroup 加载矩阵 C 的一个 8 × 4 8\times 4 8×4 段。
  • threadgroup 内的具体分布取决于矩阵 C 是 FP16还是 FP32,并且与布局无关。

在两种工作模式下,均使用32位宽(部分合并)的加载指令访问矩阵 C 的元素。

Turing Tensor Cores

图 8 总结了 NVIDIA Turing 架构中张量核的操作数矩阵元素到线程的分布。Turing 的张量核心支持三种新的精度模式:1位、4位和8位,以及三种新的图块大小:8位和16位模式的 32 × 8 × 16 32\times 8\times 16 32×8×16 8 × 32 × 16 8\times 32\times 16 8×32×16,4位模式为 8 × 8 × 32 8\times 8\times 32 8×8×32
figure 8Figure 8: Distribution of operand matrix elements to threads for tensor cores in the RTX 2080 (Turing).

在撰写本文时,对1位模式的支持才启用,并且似乎不适用于文中的系统。因此,本文其余部分不提供1位模式的分析。

Turing 的元素到线程的分布比 Volta 更简单。具体而言,

  • 每个操作数矩阵元素仅加载一次。
  • 两种图块尺寸 32 × 8 × 16 32\times 8\times 16 32×8×16 8 × 32 × 16 8\times 32\times 16 8×32×16 都采用相同的分布。
  • 对于所有模式和配置,每行或列(取决于模式和操作数矩阵)由 threadgroup 加载,并且连续的 threadgroup 加载连续的行或列。

Machine ISA interface

本节总结了作者所了解的有关如何在机器指令集架构级别访问 Tensor Core 的知识。 对于 NVIDIA GPU,这个层次通常称为 SASS。这里的分析基于使用 NVIDIA 的 cuobjdump 工具检查 SASS 反汇编。

论文发现wmma.loadwmma.store PTX 指令是通过分解为一组普通的 SASS 加载(LD.E.64LD.E.64LD.E.SYS) 和存储 (ST.E.SYS) 指令来实现的。这表明 Tensor Core 直接从普通 GPU 寄存器文件中访问操作数矩阵片段。更详细地说,发现wmma.load.c PTX 指令被分解为一组LD.E.SYS指令。

对于操作数矩阵 A 和 B,根据操作数矩阵布局是行优先还是列优先,将wmma.load PTX 指令拆分为四个 64 位加载 (LD.E.64) 或两个 128 位负载 (LD.E.128)。

图 9 说明了单个wmma.mma PTX 指令所对应的 Volta 的 SASS 代码。
在这里插入图片描述
从图中可以看出,

  • 矩阵乘法累加运算是通过新的 SASS 指令HMMA实现的。
  • 每个HMMA指令有四个操作数,每个操作数使用一对寄存器。
  • 由不同内存操作访问的一对相邻寄存器使用单个寄存器标识符编码在HMMA指令中(通过比较HMMA以及加载和存储使用的寄存器可以推断出)。例如,论文分析图 9 中第一条HMMA指令中的R8表示寄存器对<R8,R7>
  • 寄存器对中较高位的寄存器标识符是指令中编码的寄存器标识符。例如,对于图 9 第一行的HMMA指令,目标寄存器R8实际上代表<R8,R7>对。 类似地,剩余的寄存器标识符实际上代表三对源操作数寄存器(<R24,R23><R22,R21><R8, R7>)。
  • 一些寄存器在图 9 中用“reuse”注释。 SGEMM Implementation 分析了 NVIDIA 针对早期 Maxwell 架构的 SASS 指令集,其中经常出现类似的注释。根据他的分析和 NVIDIA 关于 GPU 寄存器文件缓存的相关论文[43],作者认为“reuse”符号表示相关操作数在下一步中被重用,因此缓存在操作数重用缓存以避免寄存器读取并可能减少 bank冲突。
Volta Tensor Cores

每个wmma.mma PTX 指令被分解为一组HMMA指令:

  • 图 9a 说明了混合精度模式的 SASS 代码。在该模式下,
    • 每条 PTX wmma.mma指令被分解成16条HMMA指令。
    • 16条HMMA指令被组织为4条HMMA指令的4个集合
    • 每条HMMA指令用" STEP<n>"标注,其中<n>的取值范围从0到3。因此,每个集合包括四个步骤。
  • 图 9b 说明了 FP16 模式的 SASS 代码,其中,
    • 单条 PTX wmma.mma指令分为四组;
    • 仅包含 2 个步骤。

图 9 还显示了 Volta Tensor Core 的累积时钟周期。wmma.mma API 在混合精度模式下的延迟比 FP16模式下低十个周期。

Turing Tensor Cores

对于 Turing,每条 PTX wmma.mma指令

  • 在4位模式下转换为单条HMMA指令;
  • 其他模式下均都分为一组四个HMMA指令。

表 I 显示了 Turing 架构上HMMA指令的累积时钟周期。 对于 16 × 16 × 16 16\times 16\times 16 16×16×16 图块大小,Turing 上混合精度模式下 wmma.mma的延迟为99个周期(表 I), 多于 Volta 的54个周期(图 9a)。混合精度模式的延迟大于 FP16模式。8位模式速度最快。4位模式的延迟最高,这可能是因为它是2080 RTX 上的一个实验特性。
在这里插入图片描述

HMMA Instruction Analysis

本节将更详细地探讨HMMA执行。

Volta

作者考察了图 9 中HMMA指令的每个"集合"的操作。如图 10a 所示,无论模式如何,当执行集合中的HMMA指令时,每个 threadgroup 将操作数矩阵 A 的 4 × 4 4\times4 4×4 图块与操作数矩阵 B 的 4 × 8 4\times 8 4×8 图块相乘,并将结果与操作数矩阵 C 相加。例如,当 threadgroup 0 执行第一组HMMA指令 (Set 1) 时,它将由操作数矩阵 A 的前四行和前四列组成的子图块与由操作数矩阵 B 的前四行和前八列组成的子图块相乘。结果通过操作数矩阵 C 的 4 × 8 4\times8 4×8 子图块进行累加,并存储在操作数矩阵 D 的 4 × 8 4\times8 4×8 子图块中。串联4个集合,threadgroup 0 完成操作数矩阵 A 的 4 × 16 4 \times 16 4×16 图块与操作数矩阵 B 的 16 × 8 16 \times 8 16×8 图块的乘法。
在这里插入图片描述

图 10b 显示了混合精度模式下 threadgroup 0 的“集合”中每个HMMA “步骤”的详细操作。HMMA指令的每个“集合”包含四个“步骤”。在每个步骤中,操作数矩阵 A 的 2 × 4 2\times4 2×4 子图块与操作数矩阵 B 的 4 × 4 4\times4 4×4 子图块相乘,并与操作数矩阵 C 的 2 × 4 2\times4 2×4 子图块累加。

类似地,图 10c 显示了 FP16模式下 threadgroup 0 的“集合”中每个HMMA“步骤”的详细操作。每组HMMA指令包含两个“步骤”。在每个步骤中,每个线程组将操作数矩阵 A 的 4 × 4 4\times4 4×4 子图块与操作数矩阵 B 的 4 × 4 4\times4 4×4 子图块相乘,并将结果与矩阵 C 累加。

经过以上步骤,threadgroup 0 完成操作数矩阵 A 的 8 × 4 8\times4 8×4 子图块与操作数矩阵 B 的 4 × 8 4\times8 4×8 子图块的乘法。

Turing

图 11 说明了 Turing GPU 架构上HMMA指令访问的元素。 Volta 中HMMA SASS 指令上发现的“step”注释在 Turing 中不存在。
在这里插入图片描述考虑到表 I 中的延迟结果并不表明并行性增加,一种可能性是类似的“步骤”由微体系结构使用状态机排序。作者认为:

  • 对于不同的图块配置,特定模式访问的元素是相似的。
  • 在 FP16 和混合精度模式下,计算模式是两个子图块之间的乘积,其中一个子图块是 8 × 8 8\times 8 8×8,另一个子图块是 16 × 8 16\times 8 16×8 8 × 16 8\times 16 8×16。 例如,对于图块大小 16 × 16 × 16 16\times 16\times 16 16×16×16 32 × 8 × 16 32\times 8\times 16 32×8×16,SET 1 中的计算是矩阵 A 的 16 × 8 16\times 8 16×8 子图块与矩阵 B 的 8 × 8 8\times 8 8×8 子图块之间的乘积,而对于图块大小 8 × 32 × 16 8\times 32\times 16 8×32×16,乘积在矩阵 A 的 8 × 8 8\times 8 8×8 子图块与矩阵 B 的 8 × 16 8\times 16 8×16 子图块之间。
  • 对于8位模式,计算模式为矩阵 A 的 8 × 16 8\times16 8×16 子图块与矩阵 B 的 16 × 8 16\times8 16×8 子图块之间的乘积。

在4位模式下,每个 wmma.mma PTX 指令都是用单个HMMA SASS 指令实现的,因此在图 11 中省略了4位模式。

Discussion

本节对上面给出的 Volta 结果进行分析,并推断出将执行分解为“集合”和“步骤”的可能理由。

回想一下,输入矩阵的每个元素都由两个不同的 threadgroup 加载。作者编写了一个微基准测试来帮助确定HMMA指令如何使用不同线程加载的片段。例如,为了确定如何使用由 thread 0 加载的操作数矩阵元素,作者更改了这些值并观察结果如何受到影响。论文发现 threadgroup 成对工作以计算结果的 8 × 8 8\times8 8×8 子图块,并将每对这样的线程组称为 octet。一个线程束中有四个 octet

表 II 显示了构成每个 octetthreadgroup 对,一般可以表示为 o c t e t X = t h r e a d g r o u p X ⋃ t h r e a d g r o u p X + 4 \mathrm{octet}\, X = \mathrm{threadgroup}\, X \bigcup\mathrm{threadgroup}\, X+4 octetX=threadgroupXthreadgroupX+4,其中 X X X 介于 0 到 3 之间。表 II 还使用符号[Row_Start: Row_End, Col_Start: Col_End]来表示每个 threadgroup 内的线程访问的操作数矩阵 A 和 B 的子图块。无论操作数矩阵的存储布局如何,threadgroup 加载的元素都保持不变。
在这里插入图片描述

表 II 显示操作数矩阵 A 和 B 的每个元素被不同 threadgroup 中的线程加载两次。这使得每个 octet 能够独立工作。具体来说,每个 octet 读取操作数矩阵 A 的 8 × 16 8\times 16 8×16 子图块、操作数矩阵 B 的 16 × 8 16\times 8 16×8 子图块和操作数矩阵 C 的 8 × 8 8\times 8 8×8 子图块,如图 12a 所示。
在这里插入图片描述为了更好地理解 octet 中线程的组织,作者分析了 octet 在不同“集合”和“步骤”中执行的计算。如图 12b 所示,在每个集合中,每个 octet 执行输入子图块之间的外积。例如,在 Set 1 中,完成输入子图块 [ a ] , [ e ] [a],[e] [a],[e] [ A ] , [ E ] [A],[E] [A],[E] 之间外积,生成部分结果 [ a A ] , [ a E ] , [ e A ] [aA], [aE], [eA ] [aA],[aE],[eA] [ e E ] [eE] [eE]。这里每个 [ a ] , [ e ] , [ A ] , [ E ] [a],[e],[A],[E] [a],[e],[A],[E] 代表一个 4 × 4 4 \times 4 4×4 子图块。为了计算 [ a E ] [aE] [aE]threadgroup 0 需要操作数矩阵 B 子图块 [ E ] [E] [E],它仅由 threadgroup 4 加载。类似地,要计算 [ e A ] [eA] [eA]threadgroup 4 需要操作数矩阵 B 子图块 [ A ] [A] [A],它仅由 threadgroup 0 加载。因此,虽然 threadgroup 不能,但 octet 可以独立工作。表 III 在图 12b 的基础上进行了扩展,将在不同集合和步骤中执行的所有外积计算制成表格。
在这里插入图片描述

A Tensor Core Microarchitecture

本节提出了一个张量核微架构,其与本文前面对 Volta 的观察结果一致。

回想一下,每个张量核每个周期完成 4 × 4 4\times4 4×4 矩阵乘法并累加。 为了实现这一目标,每个张量核必须能够在每个周期执行16个四元素点积(four-element dot-products,FEDP)。如图 9 和 图 10b 所示,在稳定状态下, threadgroup 需要两个周期来生成输出矩阵的 2 × 4 2\times 4 2×4 子图块。 因此,在 warp 内的所有线程中,HMMA指令每个周期执行32个 FEDP。由于每个张量核每个周期只能完成16个 FEDP,因此 SM 中每个子核需要两个张量核才能达到满吞吐量。为了证实这一点,作者编写了一个微基准测试,它重复执行HMMA操作,改变每个线程块内的 warp 数量,并保持并发执行的线程块数量不变。如图 12c 所示,该微基准测试显示单个 SM 上只能同时执行 4 个 warp,但 Titan V SM 每个 SM 有 8 个张量核。 因此,每个 warp 似乎都利用了两个张量核。

接下来,考虑寄存器访问带宽。图 9a 中的数据表明HMMA指令的最小启动间隔是两个周期。有三个源操作数,并且如第 III-C 节中所述,对于每个源操作数,读取一对32位寄存器。综合考虑这些因素,总寄存器读取带宽为每个线程束每两个周期 32 × 2 × 3 × 32 = 6 k b 32\times2\times3\times32 = 6\mathrm{kb} 32×2×3×32=6kb。 此带宽足以让线程束每两个周期获取以下值:

  • 操作数 A 的八个 2 × 4 2\times4 2×4 FP16子图,
  • 操作数 B 的八个 4 × 4 4\times4 4×4 FP16子图,
  • 以及操作数 C 的八个 2 × 4 2\times4 2×4 FP32子图或八个 4 × 4 4\times4 4×4 FP16子图。

假设每个线程束访问两个张量核,每个张量核的寄存器带宽为每个时钟周期每个线程束1.5kb。

NVIDIA 指出在 Volta 中 INT 和 FP32指令可以共同下发[26]。另一方面,Dissecting the NVIDIA Volta GPU Architecture via Microbenchmarking 报告张量核运算不能与整数和浮点算术指令共同发出。 论文认为原因是张量核可能正在使用与 INT 和 FP32核关联的寄存器文件访问端口。Titan V SM 内部有64个 INT 和64个 FP32 ALU,共计128个 ALU。由于一个 SM 中的8个张量核共享对寄存器文件的访问权限,每个张量核每个周期应该能够访问每个源操作的 128 8 × 32 = 16 × 32 = 512 \frac{128}{8}\times32=16\times32=512 8128×32=16×32=512 比特。假设每个 ALU 有3个源操作数(以支持乘法累加运算),这意味着每个张量核可以访问1.5kb/cycle。

图 13 展示了论文提出的张量核微架构。每个线程束使用两个张量核。假设线程束内每个张量核经由两个不同的 octet 访问。每个张量核有16个专用 SIMD 通道,每个 octet 有8个通道,每个 threadgroup 有 4 个通道。每个 threadgroup 通道将操作数送入内部缓冲区。

在这里插入图片描述

对于操作数矩阵 A 和 C,每个 threadgroup 将操作数提取到其单独的缓冲区,而对于操作数矩阵 B,两个 threadgroup 都将操作数提取到共享缓冲区。操作模式和步骤决定了从中获取每个操作数的 threadgroup 通道。缓冲器为16个 FP16 FEDP 单元提供数据。在每个 FEDP 单元内部,乘法在第一阶段并行执行,累加发生在三个阶段,总共四个流水线阶段。由于每个张量核由16个 FP16 FEDP 单元组成,因此每个周期能够完成一个 4 × 4 4\times4 4×4 矩阵乘法。

参考资料:

  • # [DOC] Where does cutlass’ detailed GEMM kernel? #526
  • Dissecting the NVIDIA Volta GPU Architecture via Microbenchmarking
  • Modeling Deep Learning Accelerator Enabled GPUs
  • NVIDIA Tensor Core微架构解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/116618.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SystemVerilog Assertions应用指南 Chapter1.38在序列匹配时调用子程序

SVA可以在序列每次成功匹配时调用子程序。同一序列中定义的局部变量可以作为参数传给这些子程序。对于序列的每次匹配,子程序调用的执行与它们在序列定义中的顺序相同。 module sub;logic a, b, clk;initial $vcdpluson();initial begin clk 1b0; a1b0; b1b0; repeat(2) (pos…

如何复制禁止复制的内容

今天找到一段代码&#xff0c;但是复制时页面提示“这个是VIP会员才有的权限”。我该怎么复制呢。 现在的平台大都是用钱说话&#xff0c;以便响应知识付费的主张。对错我就不说了&#xff0c;我认为既然我有权利看到代码&#xff0c;当然也有权把他复制下来。这并不涉及侵权。…

【嵌入式-Linux】安装实时内核

原文链接&#xff1a;Docs 所有内容链接&#xff1a;博客学习目录_Howe_xixi的博客-CSDN博客 参考链接&#xff1a;Ubuntu 18.04安装 RT-PREEMPT 实时内核及补丁【过程记录】_fully preemptible kernel(rt)_黄小白的进阶之路的博客-CSDN博客 Ubuntu20.04编译Linux内核_zstd: n…

【wvp】wvp设备上可以开启tcp被动模式

目录 开启了 tcp被动模式 开启UDP模式 地平线不支持这种tcp情况 开启了 tcp被动模式 我的理解是zlm就会是tcp被动收流模式 tcpdump -i any host 10.1.3.7 and tcp 而wvp->浏览器&#xff0c;是SRTP,其实还是基于zlm8000的udp端口出来的 开启UDP模式 tcpdump -i any host…

【Reinforcement Learning】Ubuntu中mujoco210 mujoco_py D4RL安装及错误解决

Ubuntu中mujoco210 mujoco_py D4RL安装及错误解决 本文根据一篇知乎文章链接在此进行配置&#xff0c;记录在配置过程中遇到的一些问题&#xff0c;原文作者的教程很详细&#xff0c;在此对原作者表示感谢&#xff5e; 直接进行知乎原文的第2.2 有效安装过程(避坑) 2.注意上…

Django viewsets 视图集与 router 路由实现评论接口开发

正常来说遵循restful风格编写接口&#xff0c;定义一个类包含了 get post delete put 四种请求方式&#xff0c;这四种请求方式是不能重复的 例如:获取单条记录和多条记录使用的方式都是get&#xff0c;如果两个都要实现的话那么得定义两个类&#xff0c;因为在同一个类中不能有…

【rust/树莓派】使用rppalembedded-graphics控制st7789 LCD屏幕

说在前面 树莓派版本&#xff1a;4bLCD模块&#xff1a;ST7789V2 240*280 LCD树莓派系统&#xff1a;Linux raspberrypi 5.15.76-v8 #1597 SMP aarch64 GNU/Linuxrust版本&#xff1a;rustc 1.73.0 模块详情 某雪的1.69inch LCD模块&#xff0c;包含杜邦线 准备工作 树莓派…

如何有效取代FTP来帮助企业快速传输大文件

在互联网的发展历史上&#xff0c;FTP是一种具有里程碑意义的协议&#xff0c;它最早出现在1971年&#xff0c;是实现网络上文件传输的基础。FTP的优点是简单、稳定、兼容性强&#xff0c;可以在不同的操作系统和平台之间进行文件交换。然而&#xff0c;时代在进步&#xff0c;…

【C语言】指针错题(类型分析)

题目&#xff1a; #include <stdio.h> int main () {int*p NULL;int arr[10] {0}; return 0; } 选项&#xff1a; A、p arr ; B、 int (* ptr )[10]& arr ; C、 p & arr [ 0 ]; D、 p & arr ; 解析&#xff1a; 1、 p 是一个指针变量&#xff0c;指…

【机器学习】模型平移不变性/等变性归纳偏置Attention机制

Alphafold2具有旋转不变性吗——从图像识别到蛋白结构预测的旋转对称性实现 通过Alphafold2如何预测蛋白质结构&#xff0c;看有哪些机制或tricks可以利用&#xff1f; 一、等变Transformer 等变Transformer是Transformer众多变体的其中一种&#xff0c;其强调等变性。不变性…

Vue非单文件组件

组件就是用来实现局部特定功能效果的代码集合&#xff0c;为的就是复用编码&#xff0c;简化项目编码&#xff0c;提高运行效率。 组件分为非单文件组件和单文件组件&#xff0c;这里介绍的是非单文件组件。 一、创建组件 创建组件的语法格式如下&#xff1a; const 组件名 …

Jmeter(十二):线程组元件第三方插件的线程组压力和负载线程详解

线程组(thread group) 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件 都必须在某个线程下。所有的任务都是基于线程组。 一个线程组可以看做一个虚拟用户组&#xff0c;线程组中的每个线程都可以理解为一 个虚拟用户。多个用户同时去执行相同的一批次任…

Git基本命令和使用

文章目录 1、Git本地库命令1.1、初始化本地库1.2、设置用户签名1.3、查看本地库状态1.4、将工作区的修改添加到暂存区1.5、将暂存区的修改提交到本地库1.6、历史版本1.7、取消commit1.8、取消暂存文件 2、分支操作2.1、查看分支2.2、创建分支2.3、分支合并时产生冲突 3、Gitee远…

Pillow(PIL)库的主要方法介绍

Pillow&#xff08;Python Imaging Library&#xff09;是Python中一个强大的图像处理库&#xff0c;它允许你进行图像的创建、打开、编辑、保存和显示等操作。Pillow 是 PIL&#xff08;Python Imaging Library&#xff09;的分支&#xff0c;支持多种图像格式&#xff0c;并提…

javaEE -7(网络原理初识 --- 7000字)

一&#xff1a;网络初识 计算机的独立模式是指多台计算机在网络中相互独立运行&#xff0c;彼此之间不共享资源或信息。在早期&#xff0c;计算机主要采用独立模式&#xff0c;每台计算机都拥有自己的操作系统、应用程序和数据&#xff0c;它们之间没有直接的连接或通信。 在…

解决LOGITECH 罗技驱动 MAC版出现的一些问题汇总!

安装前将之前的安装文件清理干净&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 罗技驱动最新安装包下载 我的鼠标是G304 1. 驱动安装一直卡在99% 运行官方下载的安装程序&#xff0c;卡住后关掉窗口。 在终端中执行以下命令&#xff1a; sudo /Users/用户名…

期 货 分 仓,资 管 分 仓,跟单软件都有哪些特点?

期货分仓软件是一种用于期货交易的软件系统。通过该系统&#xff0c;机构可以在一个主账户中同时使用多个子账户操作多个期货合约&#xff0c;并且可以设置不同资金量的用户不同的开仓比例。 由于目前国内的期货市场对于国际市场的品种还处于不规范阶段&#xff1a;一方面是保证…

Openssl数据安全传输平台003:Protobuf - 部署

文章目录 Github代码仓库位置一、Windows环境配置生成库文件之后—>参考3.3 配置VS1. 先将平台设置为所有平台2. 配置属性 >> C/C >> 常规 >> 附加包含目录3. 配置属性 >> C/C >> 预处理器 >> 预处理器定义,添加4. 配置属性 >> C…

1024程序员节:理解编码背后的艺术

1024的含义 "1024"在中国互联网文化中有两个主要的含义&#xff1a; 1024是2的10次方&#xff0c;这在计算机科学中是一个重要的数字&#xff0c;因为计算机的基础是二进制。因此&#xff0c;程序员们常常把1024作为一个特殊的日子来庆祝&#xff0c;也就是10月24日…

laravel框架介绍(一)

laravel框架是一套简洁&#xff0c;优雅的PHPWeb开发框架。