传统上,分布式计算基于消息传递模型,其中数据以消息的形式从处理器传递到处理器。RPC 实际上是相同的模型(或非常接近)。

DSM 是分布式系统的所有节点(处理器)共享的虚拟地址空间。程序访问 DSM 中的数据的方式与访问传统计算机虚拟内存中的数据的方式非常相似。在具有 DSM 的系统上,数据在不同计算机的本地存储器之间移动的方式与它们在一台计算机的 RAM 和外部存储器之间移动的方式相同。

6.1 DSM的优势

  1. 在消息传递模型中,程序员通过显式的消息发送和接收操作提供对共享数据的访问。在这种情况下,需要对算法进行量化,保证缓冲区中信息的及时变化,并对数组索引进行变换。所有这些都使编程和调试变得非常复杂。DSM 对程序员隐藏数据传输,并为他提供他已经习惯在多处理器上使用的共享内存抽象。使用 DSM 进行编程和调试要容易得多。
  2. 在消息传递模型中,数据在两个不同的地址空间之间移动。这使得在进程之间传输复杂的数据结构变得非常困难。此外,通过引用传递数据和传递包含指针的数据结构通常是复杂且昂贵的。DSM 还允许您通过引用传递数据,这简化了分布式应用程序的开发。
  3. 所有节点的总物理内存量可能很大。应用程序可以使用如此大量的内存,而不会产生与传统磁盘交换系统相关的开销。由于处理器速度的增长速度快于内存速度,同时出现了非常快速的通信,这一优势变得越来越重要。
  4. DSM 系统几乎可以无限增长,这与具有共享内存的系统不同,即 是可扩展的。
  5. 为共享内存多处理器编写的程序原则上可以在 DSM 系统上运行而无需任何更改(至少它们可以很容易地移植到 DSM 系统)本质上,DSM 系统克服了多处理器的体系结构限制并减少了编写所需的工作量分布式系统的程序。这些通常在固件中实现,但近年来已经有几个商业 MPP 与 DSM 在硬件中实现(凸 SPP,KSR1)。

6.2 DSM实现算法

以下问题是 DSM 实施的核心。

  1. 如何维护有关已删除数据位置的信息。
  2. 如何在访问远程数据时减少与实施通信协议相关的通信延迟和高昂的开销成本。
  3. 如何在多个节点上同时提供共享数据以提高系统性能。

让我们考虑四种基本的 DSM 实现算法。

6.2.1 中央服务器算法

所有共享数据都由中央服务器维护。它在读取请求时将数据返回给客户端,在写入请求时它会更正数据,并将回执发送回客户端。当服务器没有响应时,客户端可以使用超时来发送重试。通过请求编号可以识别重复的写入请求。如果对服务器的多次重复调用仍未得到应答,应用程序将收到否定响应代码(这是由客户端提供的)。

该算法易于实现,但服务器可能成为瓶颈。

为避免这种情况,可以将共享数据分布在多个服务器上。在这种情况下,客户端必须能够确定每次访问共享变量时要联系哪个服务器。一次向所有服务器发送请求是不可取的,因为它不会减少服务器上的负载。最好的解决方案是根据地址分配数据并使用映射功能确定正确的服务器。

6.2.2 迁移算法

与之前的算法不同,当一个数据请求被发送到它的位置时,在这个算法中数据的位置会发生变化——它们会移动到需要它们的地方。这允许在本地执行顺序数据访问。迁移算法只允许一个节点在任何给定时间访问一个数据元素。
通常迁移整个页面或数据块,而不是请求的数据单元。这使您可以利用应用程序中数据访问的固有局部性来降低迁移成本。但是,当页面在节点之间迁移时经常只提供少量请求时,这种方法会导致抖动。一些系统允许您设置页面被强制保留在节点中的时间,以便在将页面迁移到另一个节点之前有时间对其执行多次访问。

迁移算法允许 DSM 与单个节点中操作系统提供的虚拟内存集成。如果 DSM 页面大小与虚拟内存页面大小相同(或它的倍数),那么您可以使用普通机器指令访问共享内存,使用硬件检查 RAM 中是否存在所需的页面并用物理地址替换虚拟地址。当然,为此,处理器的虚拟地址空间必须足以寻址整个共享内存。在这种情况下,一个节点中的多个进程可以共享同一个页面。

为了确定数据块的位置,迁移算法可以使用跟踪块移动的服务器,或者使用每个节点中的提示机制。广播请求也是可能的。

6.2.3 读取的乘法算法

以前的算法只允许一个节点(该数据所在的节点)中的进程在任何时候访问共享数据。该算法通过数据块乘法机制扩展了迁移算法,允许多个节点能够同时读取和写入数据,或者一个节点能够读取和写入数据(多读一写协议)。并发读取访问的可能性提高了性能,但写入破坏或更正数据块的任何过时副本的成本很高。

使用这种算法时,需要跟踪所有数据块及其副本的位置。例如,块的每个所有者都可以跟踪其副本的位置。
当读取次数明显超过写入次数时,该算法可以降低平均读取访问成本。

6.2.4 全传播算法

该算法是先前算法的扩展。它允许许多节点同时对共享数据进行读写访问(多读取器和多写入器协议)。由于许多节点可以并行写入数据,因此有必要控制对它们的访问以保持数据一致性。

确保数据一致性的一种方法是使用特殊过程来订购内存修改。所有希望修改共享数据的节点都必须将其修改发送到该进程。它将为每个修改分配一个连续的编号,并将其与修改一起广播到所有具有被修改数据块副本的节点。每个节点将按照其编号的升序进行修改。收到的修改数量的差距将意味着丢失一个或多个修改。在这种情况下,节点可能会请求丢失的修改。

上述所有算法都是低效的。效率只能通过改变内存访问的语义来实现。

6.3 一致性模型

一致性模型是程序和内存之间的一种协议,它表明如果程序遵循一定的规则,内存模块的操作就会正确,但是如果违反了程序的要求,那么内存不保证正确执行读/写操作。本章讨论分布式内存系统中使用的主要一致性模型。

6.3.1 强一致性

满足条件的一致性模型:对地址 X 的内存位置的读操作必须返回地址 X 最近的写操作写入的值,称为强一致性模型。上面的条件看起来很自然很明显,但是它假设系统有绝对时间的概念来确定最近的写操作。

所有单处理器系统都提供强一致性,但在分布式多处理器系统中情况要复杂得多。假设变量 X 位于机器 B 的内存中,并且在机器 A 上运行的进程试图在时间 T1 读取该变量的值。为此,机器 B 发送对变量 X 的请求。稍后,在 T2 时刻,机器 B 上运行的进程执行了向变量 X 写入新值的操作。为确保严格一致性,读取操作必须返回机器 A 的变量旧值,无论机器 A 位于何处以及两次 T1 和 T2 彼此之间的距离如何。但是,如果 T1-T2 为 1 纳秒且机器相距 3 米,

P1: W(x)1 P1: W(x)1
--> t --> t
P2: R(x)1 P2: R(x)0 R(x)1
      
а) б)

a) 严格一致的内存
b) 没有严格一致性 的内存

6.3.2 一致的一致性

强一致性是编程的理想模型,但不幸的是,对于程序员来说,它无法在分布式系统中实现。然而,实践经验表明,在某些情况下,使用较弱的模型是可能的。所有这些方法都依赖于必须观察某些写入和读取事件的顺序这一事实。
Lamport 在 1979 年首先定义了顺序一致性。

  • 根据他的定义,顺序内存一致性模型必须满足以下条件: 执行结果必须与所有处理器的语句都以某种顺序执行相同,其中每个单独的处理器的语句按以下确定的顺序定位该处理器的程序。

这个定义意味着当并行执行时,所有进程必须看到相同的内存写入序列。

顺序一致性并不能保证读取操作将返回另一个进程在纳秒甚至一分钟之前写入的值,该模型仅保证所有进程都知道所有写入内存的顺序。如果程序不使用同步机制来规范内存访问操作,则在具有顺序一致性(实际上是严格一致性)的系统中重复执行并行程序的结果可能与先前执行同一程序的结果不一致.

一个程序正确执行的两个例子。这些示例使用以下符号:

  • W(x)1 - 将值 1 写入变量 x;
    R(x)0 - 从变量 x 中读取值 0。
P1: W(x)1 W(y)1
P2: W(z)1
P3: R(x)0 R(y)0 R(z)1 R(y)0
P4: R(x)0 R(y)1 R(z)1 R(x)1

在此示例中,进程按 W(z)1、W(x)1、W(y)1 或 W(x)1、W(z)1、W(y)1 的顺序查看记录。

P1: W(x)1 W(y)1
P2: W(z)1
P3: R(x)0 R(y)1 R(z)0 R(y)1
P4: R(x)1 R(y)1 R(z)0 R(x)1

在这个例子中,进程以 W(x)1, W(y)1, W(z)1 的顺序查看记录。同一程序的两个示例运行不正确。

P1: W(x)1 W(y)1
P2: W(z)1
P3: R(x)0 R(y)0 R(z)1 R(y)0
P4: R(x)0 R(y)1 R(z)0 R(x)1

进程 P3 和 P4以不同的顺序查看记录 W(y)1 和 W(z)1 。

P1: W(x)1 W(y)1
P2: W(z)1
P3: R(x)1 R(y)0 R(z)1 R(y)1
P4: R(x)0 R(y)1 R(z)1 R(x)0

进程 P4以不同于它们在进程 P1 中执行的顺序查看记录 W(x)1 和 W(y)1 。

上述迁移算法实现了顺序一致性。

  • 顺序一致性也可以如下实现。可写页面被传播,但共享内存操作必须在某个处理器发出的前一个写操作完成之前开始,即 相应页面的所有副本都将被更正(所有记录都按顺序执行,在执行期间阻止所有进程的工作)。在具有有序广播机制的系统上内存修改操作的请求被发送给相应页面(包括其自身)副本的所有所有者。同时,进程的工作不会被阻塞。一个处理器可以发出多个数据修改请求。在此处理器发出的所有修改请求完成之前,不得执行任何读取操作(处理器将接收并执行其请求)。

6.3.3 因果一致性

因果内存一致性模型比顺序模型更弱,因为它并不总是要求所有进程看到相同的内存写入序列,而是区分潜在的依赖写入,并且

考虑一个例子。假设进程 P1 修改了变量x,然后进程 P2 读取x并修改了y。在这种情况下,x 的修改和y的修改可能是因果相关的,因为y的新值可能取决于 x的读取值。另一方面,如果两个过程同时改变了不同变量的值,那么这些事件之间就没有因果关系。因果独立的操作称为并行操作。

内存一致性的因果模型由以下条件决定:系统的所有进程必须以相同的方式观察一系列潜在因果相关的写操作,不同节点可以以不同的顺序观察并行写操作.

例子。

(a) 违反因果一致性模型

P1: W(x)1
P2: R(x)1 W(x)2
P3: R(x)2 R(x)1
P4: R(x)1 R(x)2

(b) 因果一致性模型的正确顺序。

P1: W(x)1 W(x)3
P2: R(x)1 W(x)2
P3: R(x)1 R(x)3 R(x)2
P4: R(x)1 R(x)2 R(X)3

在为页面传播的情况下实现因果一致性时,执行共享内存操作只需要等待执行那些可能具有因果关系的先前写入操作。并发写入不会延迟共享内存操作,也不需要广播不可分割。

编译器可以通过分析程序语句对数据的依赖性来确定潜在的因果依赖性。

DSM 系统可以通过对每个处理器上的所有记录进行编号,将这些编号与正在修改的数据一起传播到所有处理器,并延迟任何处理器上的任何修改,直到它接收到写入延迟修改的处理器的所有修改来做到这一点。

6.3.4 PRAM 一致性和处理器一致性

PRAM(Pipelined RAM)一致性定义如下:一个处理器执行的写操作按执行顺序对所有其他处理器可见,但不同处理器执行的写操作可以按任何顺序查看。

具有 PRAM 一致性的系统中的有效事件序列示例。

P1: W(x)1
P2: R(x)1 W(x)2
P3: R(x)1 R(x)2
P4: R(x)2 R(x)1

PRAM 一致性模型的优势在于其易于实现,因为在一个处理器上的写入操作可以流水线化:无需等待先前的写入操作完成(例如修改所有页面副本)即可开始使用共享内存的操作,您只需要确保所有处理器都以相同的顺序看到这些记录。
PRAM 一致性会导致反直觉的结果。例子:

进程 P1 进程 P2
.......... ..........
a = 1; b = 1;
if (b==0) kill (P2); if (a==0) kill (P1);
.......... ..........

这两个进程都可以被杀死,这在顺序一致性下是不可能的。
处理器一致性模型与 PRAM 一致性模型的不同之处在于它还需要内存一致性:对于每个变量 x,处理器修改该变量的顺序是一致的,对不同变量的写入是并发的。因此,除了对每个处理器的记录进行排序之外,还添加了将记录排序到变量或组中。

6.3.5 一致性差

一致性 PRAM 模型和具有更高一致性的处理器模型比严格一致性更有效率和效率,但它们对许多应用程序的限制并不总是必要的,因为它们需要所有处理器都知道在某个处理器上执行的写入操作的顺序。

例如,考虑一个循环读取和写入临界区中某些变量值的进程。即使其他处理器在第一个进程退出临界区之前没有尝试访问这些变量 ,为了满足上述一致性模型的要求,它们必须按照执行顺序查看第一个处理器的所有记录,其中,当然,完全没有必要。这种情况下最好的解决方案是让第一个进程完成临界区的执行,然后才将修改后的变量的值发送给其余的进程,而不用担心发送中间结果,并且他们在关键部分的评估顺序。

1986年提出的弱一致性模型(Dubois et al.)是基于变量间特殊同步变量的选择,由以下规则描述:

  1. 对同步变量的访问由顺序一致性模型决定;
  2. 对同步变量的访问被拒绝(延迟),直到所有先前的写操作都完成;
  3. 在所有先前对同步变量的访问完成之前,禁止访问数据(写入、读取)。

第一条规则指定所有进程以特定(相同)顺序查看对同步变量的访问。

第二条规则保证了处理器执行同步变量访问操作只有在管道被弹出后(在所有处理器上完成该处理器发出的所有先前变量写入操作)才能执行。第三条规则规定,在访问普通(非同步)变量进行读写时,之前对同步变量的所有访问都必须完全完成。通过在访问共享变量之前执行同步,进程可以确保它将获得该变量的正确值。

a) 有效事件序列的示例。

P1: W(x)1 W(x)2 S
P2: R(x)1 R(x)2 S
P3: R(x)2 R(x)1 S

b) 无效事件序列的示例。

P1: W(x)1 W(x)2 S
P2: S R(x)1

与以往的一致性模型不同,弱一致性模型关注的是批量读/写操作的一致性。此模型对于很少对共享变量进行单一(隔离)访问的应用程序最有效。

6.3.6 输出一致性

在弱一致性的系统中,访问同步变量时会出现问题:系统没有关于此访问目的的信息——要么进程已经完成了对共享变量的修改,要么正准备读取同步变量的值。共享变量。为了更有效地实现一致性模型,系统必须区分两种情况:进入临界区和退出临界区。

在输出一致性模型中,引入了访问同步变量的特殊函数:

(1) ACQUIRE——捕获同步变量,通知系统进入临界区;

(2) RELEASE——释放同步变量,决定临界区的结束。

捕获和释放用于组织对所有共享变量的访问,而不是对受此同步变量保护的那些变量的访问。这种共享变量称为受保护变量。

具有输出一致性的模型的有效事件序列示例。(Acq(L) - 同步变量 L 的捕获;Rel(L) - 同步变量的释放)。

P1: Acq(L) W(x)1 W(x)2 Rel(L)
P2: Acq(L) R(x)2 Rel(L)
P3: R(x)1

以下规则定义了输出一致性模型的要求:

  1. 在访问共享变量之前,必须完全完成给定处理器对同步变量的所有先前捕获。
  2. 在释放同步变量之前,必须完成处理器先前执行的所有读/写操作。
  3. 同步变量的捕获和释放操作的实现必须满足处理器一致性的要求(不需要顺序一致性)。

如果满足所有这些要求并且使用捕获和释放方法,则执行程序的结果将与在具有顺序一致性模型的系统中执行该程序时相同。

输出一致性有一个修改 - 懒惰。与所描述的(精力充沛的)退出一致性相比,它不需要在退出临界区时推出所有已修改的数据。相反,当请求临界区条目时,将受保护的共享数据的当前值传递给进程(例如,从最后进入由该同步变量保护的临界区的进程)。重新进入同一进程的关键部分不需要任何消息交换。

6.3.7 输入一致性

这种一致性是关注关键部分使用的一致性模型的另一个例子。和之前的模型一样,这种一致性模型需要程序员(或编译器)使用锁定/释放机制来执行临界区。但是,该模型要求每个公共变量都与某个同步变量(例如信号量或事件)相关联,而如果访问数组元素或各种单独的变量可以独立(并行)完成,那么这些数组元素(公共变量)必须与不同的同步变量相关联。因此,在同步变量和它们保护的公共变量之间引入了一个链接。

此外,由单个同步变量保护的临界区可以有两种类型:

  • 具有独占访问权限的部分(用于修改变量);
  • 具有非独占访问权限的部分(用于读取变量)。

考虑使用同步变量。

  • 每个同步变量都有一个临时所有者——最后一个进程获得了对该变量的访问权。该所有者可以在循环中执行关键部分,而无需向其他处理器发送消息。当前不拥有同步变量但需要捕获它的进程必须向该变量的当前所有者发送请求,以获取该变量的值和同步变量的所有权。同步变量允许有多个所有者,但前提是与该变量关联的共享数据是只读的。

以下是定义输入一致性模型的正式规则:

  1. 一个进程直到所有被捕获的同步变量保护的进程变量都被更新后才能获取同步变量;
  2. 一个进程无法在独占模式下获取同步变量(以修改受保护的数据),直到拥有该变量的另一个进程(即使在非私有模式下)释放它;
  3. 如果一个进程在独占模式下获取了一个同步变量,那么即使在非独占模式下也没有进程能够获取它,直到第一个进程释放这个变量并且在请求该进程的进程中更新了受保护变量的当前值同步变量。

6.3.8 比较一致性模型

所描述的内存一致性模型之间的差异取决于模型的局限性、实现的难易程度和编程方法。下表定义了所描述的内存一致性模型的区别特征。

(a) 不使用同步操作的一致性模型。

一致性 描述 
严格的 按绝对时间排序对共享数据的所有访问 
持续的 所有进程以相同顺序查看所有共享数据记录 
因果关系 所有进程以相同的顺序查看所有因果相关的数据记录
处理器 PRAM 一致性 + 内存一致性
PRAM 所有处理器以相同的顺序查看任何处理器的条目

(b) 具有同步操作的一致性模型。

一致性 描述 
虚弱的 只有在执行了同步之后,共享数据才能被认为是一致的。
通过输出 共享数据离开临界区后变得一致
通过输入 与临界区关联的共享数据在输入时变得一致

6.4 一致性协议

WRITE-INVALIDATE - 通知副本的所有所有者它们是无效的。

WRITE-UPDATE - 为所有所有者组织更新副本。

  • 选择取决于读取和写入的频率,以及通知和更新的时间。

6.5 设计考虑

6.5.1 页面 DSM

共享内存被分成相同长度的部分——页或块。如果您选择的长度与处理器 RAM 页面(如果它们的内存被分页)的长度匹配(或倍数),那么您可以使用内存保护机制来检测丢失的 DSM 页面和用于替换虚拟的硬件机制地址与物理地址。

基于缓存(Convex SPP)的硬件实现也可以归于同类型的 DSM(它事先对内存的内容一无所知)。

6.5.2 基于共享变量的 DSM

在具有共享变量的 DSM 系统中,处理器之间仅共享单个数据结构。程序员必须准确地确定程序中哪些变量应该共享,哪些不应该共享。

了解共享变量的使用模式可以让您使用更有效的一致性协议。

考虑以下程序,该程序通过将所有处理器上的所有变量相乘并在它们之间分配循环迭代来自动并行化。

s = 0;
izer = 0;
for (i = 1; i < L2-1; i++)
{r = A[i-1]*A[i+1];C[i] = r;s = s + r*r;if (A[i]==0) { izer = i};
}
A[izer] = 1;
  • 循环内的变量用于以下模式:

A - 只读;

r - 私有的(实际上不是共享的);

C - 单独使用(任何数组元素被不超过一个进程修改,并且没有进程读取被其他人修改的元素);

s - 用于求和的减少变量;

izer - 一个变量,存储数组 A 的最后一个零元素的索引;

不需要将变量 A 和 r 带入一致状态。

为了使数组 C 进入一致状态,在循环结束时,每个进程将其在数组 C 中的所有更改发送给其余进程。

对于变量 s,在循环结束时,需要执行额外的归约操作——将不同处理器收到的所有部分和在其变量 s 的副本中相加,并将结果发送给所有处理器(如果变量 s 的初始值不为零,必须考虑到这一点)。

退出循环时,必须为所有处理器上的 izer 变量分配在最大次数的循环迭代中获得的值(需要在每个处理器上固定为变量赋值的最大迭代次数. 当在处理器之间通过连续块分配迭代时,足以解决变量由每个处理器更改的事实)。

在循环之外,A[izer] 不需要保持一致,因为每个处理器运行相同的语句,将相同的值分配给变量的所有副本。

6.5.3 基于对象的 DSM

最后一组由具有分布式共享内存对象组织的多处理器系统组成。与所考虑的所有其他系统不同,面向对象的 DSM 系统的程序不能直接使用共享变量,而只能通过特殊的方法函数。并行程序执行支持系统在接收到使用某个共享变量的请求后,对其进行处理,同时保持共享数据的一致状态。所有的控制都只通过软件来进行,在使用数据迁移来平衡处理器负载的情况下,很难利用处理器本地内存中数据位置的接近性。

在这种情况下,由于通过函数访问数据而导致的效率损失是完全可以接受的,因为它们可以通过负载平衡实现的增益来完全补偿。

6.分布式共享内存(DSM - Distributed Shared Memory)相关推荐

  1. GPU 共享内存bank冲突(shared memory bank conflicts)

    GPU 共享内存bank冲突(shared memory bank conflicts) 时间 2016-11-05 21:47:58 FindSpace 原文 http://www.findspac ...

  2. 共享内存 传一个类指针_共享内存介绍:Shared Memory

    In computer hardware, shared memory refers to a (typically large) block of random access memory (RAM ...

  3. Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析

    出自:http://blog.csdn.net/luoshengyang/article/details/6939890 在Android系统中,针对移动设备内存空间有限的特点,提供了一种在进程间共享 ...

  4. Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(6)

    接下来,我们再来看看server模块的实现.在external/ashmem/common目录下,只有一个源文件SharedBufferServer.cpp,它实现了内存共享服务SharedBuffe ...

  5. Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(7)

              同样,我们需要为这个Client端应用程序编译一个编译脚本,在external/ashmem/client目录下,新建一个Android.mk文件,它的内容如下所示: LOCAL_ ...

  6. 分布式共享内存两种实现方式

    分布式共享内存 这里,我们介绍两种分布式共享内存,一种是分布式共享内存,另外一种是naive分布式共享内存 简单的分布式共享内存 所有的进程去访问一个共享内存,这个共享内存是虚拟的,他可能分布在不同的 ...

  7. showdialog 尝试读取或写入受保护的内存_TreadMarks: 基于工作站网络的共享内存计算...

    TreadMarks: 基于工作站网络的共享内存计算 以前学MIT6.824时看过TreadMarks相关论文,这篇论文当时只翻译了一半.最近无意中看到这篇未完成的翻译,google了下发现仍然没有人 ...

  8. 如何查询oracle的共享内存,[20190104]ipcs查看共享内存段.txt

    [20190104]ipcs查看共享内存段.txt --//数据库启动异常,有时候会留下一些共享内存段没有清理,需要使用ipcrm清理. --//由于服务器上跑2个实例,必须选择正确的共享内存段,否则 ...

  9. Linux访问其他进程空间,Linux环境进程间通信系列(五):共享内存

    共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A . B 共享内存的意思是,同一块物理内存被映射到进程 A . B 各自的进程地址空间.进程 A 可以即时看到进程 B ...

最新文章

  1. Java中的I/O模型总结(八股文自述)
  2. 循环查询sql带逗号(,)分隔的数据 以及一对多数据转化为逗号(,)分割数据...
  3. (Oracle学习笔记) sql*plus命令
  4. 图像相似度算法的C#实现及测评
  5. 【文文殿下】网络流学习笔记
  6. .Net PetShop 4.0的缓存处理
  7. 蓝桥杯vip答案java_Java实现 蓝桥杯VIP 算法训练 麦森数
  8. 工业互联网解决方案创新应用报告(2020)
  9. Eclipse中错误为 Access restriction 的解决方案
  10. 【jvm】jvm优化 jvm linux 大页
  11. Quay (2) - 镜像常规操作
  12. STM32工作笔记0013---认识UCOS系统
  13. 小白的java学习之路 “ 选择结构(一)”
  14. asp.net mvc中加入log4net记录错误日志
  15. 【转】使用频率最高的美语口语296句
  16. RMAN使用备份传输表空间
  17. 用HFFS实例讲解多频天线设计
  18. RiskCloud-基于Markov算法精准的FTA、 JSA、FMEA软件
  19. 用java写蒙特卡洛模拟_java实现蒙特卡洛模拟求解渗透问题
  20. BootStrap快速入门

热门文章

  1. The Greatest Show on Earth
  2. 【Python游戏】用Python实现一个测试你智商的小游戏——24点,过不了三关的remake(附源码)
  3. word-取消超链接的两个步骤
  4. html post密码加密,京东post登陆参数js分析,密码加密的RSA加密实现
  5. word文件的打开密码忘记了怎么办
  6. ip4标准(ip4网段)
  7. 《Spring Web Flow 实践》
  8. CTFHub HG泄露
  9. 解决win11系统任务栏(通知区域)蓝牙图标不显示问题
  10. XWPFDocument 导出word 文字+图片