diff --git a/chapter_distributed_training/collective.md b/chapter_distributed_training/collective.md
index bf4b819..164be65 100644
--- a/chapter_distributed_training/collective.md
+++ b/chapter_distributed_training/collective.md
@@ -6,11 +6,11 @@ Centers),以及如何在数据中心中高效实现集合通讯,从而让
### 在数据中心的梯度计算
-
+
:width:`800px`
:label:`ch10-datacentre`
-:numref:`ch10-datacentre` 描述了一个典型的用于深度学习模型训练的数据中心。数据中心中的训练服务器一般会有多个设备。如需增加服务器,我们会将多个训练服务器放置在一个机柜(Rack)上,同时接入一个架顶交换机(Top
+ :numref:`ch10-datacentre` 描述了一个典型的用于深度学习模型训练的数据中心。数据中心中的训练服务器一般会有多个设备。如需增加服务器,我们会将多个训练服务器放置在一个机柜(Rack)上,同时接入一个架顶交换机(Top
of Rack
Switch)来连接多个服务器。当一个机柜满的时候,我们可以通过在架顶交换机之间增加骨干交换机(Spine
Switch),接入新的机柜。通过这种方式,我们可以在数据中心内不断增加服务器,从而为神经网络的训练提供海量的算力和内存。目前的商用数据中心可能拥有超过一百万台服务器。
@@ -31,7 +31,7 @@ GPU),而在一个服务器内的多个设备可以通过高速机内网络
为了在数据中心中高效完成梯度平均的操作,我们往往会实现
Allreduce算法。这个算法诞生的背景是:传统计算平均梯度的方法往往是在集群中找出一个设备来收集本地梯度,计算平均梯度,然后再将平均梯度广播到全部的设备。这种做法易于实现,但是其引入了两个问题。首先,多设备共同给这个聚合设备发送数据的时候,在聚合设备上往往会产生严重的带宽不足和网络拥塞。其次,单设备需要负担大量的梯度平均的计算,而受限于单设备上的有限算力,这种平均计算会受限于算力瓶颈。
-
+
:width:`800px`
:label:`ch10-allreduce-state`
@@ -41,12 +41,12 @@ Allreduce算法。这个算法诞生的背景是:传统计算平均梯度的
= 1 + 2 +
4)。为了计算平均梯度,每个设备只需要在最后将梯度之和除以设备数量即可(分区1的最终结果为7除以3)。
-
+
:width:`800px`
:label:`ch10-allreduce-process`
Allreduce算法会把梯度的加和计算拆分成$M-1$个Reduce步骤和$M-1$个Broadcast步骤(其中$M$是节点的数量)。Reduce步骤是为了计算出梯度的和(Summation),Broadcast步骤是为了把梯度之和广播给全部的节点。为了说明这些步骤的执行过程,我们利用
-:numref:`ch10-allreduce-process` 。Allreduce算法由Reduce步骤开始,在第一个Reduce步骤中,Allreduce算法会对全部节点进行配对(Pairing),让他们共同完成梯度相加的操作。在 :numref:`ch10-allreduce-process` 的第一个Reduce步骤中,设备1和设备2进行了配对共同对分区1的数据相加。其中,设备2把本地的梯度数据1发送给设备1,设备将接收到1和本地的分区1内的梯度数据:2进行相加,计算出中间(intermediate)梯度相加的结果:3。于此同时,设备1和设备3进行配对,共同完成对分区3的数据相加。而设备3和设备2进行配对,共同完成对于分区2的数据相加。
+ :numref:`ch10-allreduce-process` 。Allreduce算法由Reduce步骤开始,在第一个Reduce步骤中,Allreduce算法会对全部节点进行配对(Pairing),让他们共同完成梯度相加的操作。在 :numref:`ch10-allreduce-process` 的第一个Reduce步骤中,设备1和设备2进行了配对共同对分区1的数据相加。其中,设备2把本地的梯度数据1发送给设备1,设备将接收到1和本地的分区1内的梯度数据:2进行相加,计算出中间(intermediate)梯度相加的结果:3。于此同时,设备1和设备3进行配对,共同完成对分区3的数据相加。而设备3和设备2进行配对,共同完成对于分区2的数据相加。
在上述Reduce的步骤中,梯度的计算实现了以下几个特性:
diff --git a/chapter_distributed_training/methods.md b/chapter_distributed_training/methods.md
index 0214529..f6ddfc9 100644
--- a/chapter_distributed_training/methods.md
+++ b/chapter_distributed_training/methods.md
@@ -4,11 +4,11 @@
### 概述
-
+
:width:`800px`
:label:`ch10-single-node`
-分布式训练系统的设计目标是:将单节点训练系统转化成**等价的**并行训练系统,从而在不影响模型精度的条件下完成训练过程的加速。一个单节点训练系统往往如:numref:`ch10-single-node`所示。一个训练过程会由多个数据小批次(mini-batch)完成。在图中,一个数据小批次被标示为**数据**。训练系统会利用数据小批次来生成梯度,提升模型精度。这个过程由一个训练**程序**实现。在实际中,这个程序往往实现了一个多层神经网络的执行过程。
+分布式训练系统的设计目标是:将单节点训练系统转化成**等价的**并行训练系统,从而在不影响模型精度的条件下完成训练过程的加速。一个单节点训练系统往往如 :numref:`ch10-single-node`所示。一个训练过程会由多个数据小批次(mini-batch)完成。在图中,一个数据小批次被标示为**数据**。训练系统会利用数据小批次来生成梯度,提升模型精度。这个过程由一个训练**程序**实现。在实际中,这个程序往往实现了一个多层神经网络的执行过程。
该神经网络的执行由一个计算图(Computational
Graph)表达。这个图有多个相互连接的算子(Operator),每个算子会拥有计算参数。每个算子往往会实现一个神经网络层(Neural
Network Layer),而参数则代表了这个层在训练中所更新的的权重(Weights)。
@@ -27,7 +27,7 @@ Network Layer),而参数则代表了这个层在训练中所更新的的权
| 多程序 | 多程序单数据:模型并行 | 多程序多数据:混合并行 |
:label:`ch10-parallel-methods`
-给定一个单节点训练系统,人们会对**数据**和**程序**分区(Partition),从而完成并行加速。:numref:`ch10-parallel-methods`总结了不同的切分方法。单节点训练系统可以被归类于
+给定一个单节点训练系统,人们会对**数据**和**程序**分区(Partition),从而完成并行加速。 :numref:`ch10-parallel-methods`总结了不同的切分方法。单节点训练系统可以被归类于
单程序单数据模式。而假如用户希望使用更多的设备来实现并行计算,他们首先可以选择对数据进行分区,并将同一个程序复制到多个设备上并行执行。这种方式是单程序多数据模式,常被称为**数据并行**(Data
Parallelism)。另一种并行方式是对程序进行分区:程序的算子会被分发给多个设备按照依次完成。这种模式是
多程序单数据模式,常被称为**模型并行**(Model
@@ -38,7 +38,7 @@ Parallelism)。
### 数据并行
-
+
:width:`800px`
:label:`ch10-data-parallel`
@@ -51,7 +51,7 @@ Communication)的Allreduce操作来完成。
### 模型并行
-
+
:width:`800px`
:label:`ch10-model-parallel-intra-op`
@@ -65,7 +65,7 @@ Parallelism)。
另一种内存不足的场景是:模型的总内存需求超过了单设备的内存容量。在这种场景下,假如我们总共有$N$个算子和$M$个设备,我们可以将算子平摊给这$M$个设备,让每个设备仅需负责$N/M$个算子的前向和反向计算,降低设备的内存开销。这种并行方式是模型并行的另一种应用,被称为**算子间并行**(Inter-operator
Parallelism)。
-
+
:width:`800px`
:label:`ch10-model-parallel-inter-op`
@@ -73,8 +73,8 @@ Parallelism)。
### 混合并行
-
+
:width:`800px`
:label:`ch10-hybrid-parallel`
-在训练大型人工智能模型中,我们往往会同时面对算力不足和内存不足。因此,我们需要混合使用数据并行和模型并行,这种方法被称为混合并行。:numref:`ch10-hybrid-parallel`提供了一个由4个设备实现的混合并行的例子。在这个例子中,我们首先实现算子间并行来解决训练程序内存开销过大的问题:该训练程序的算子1和算子2被分摊到了设备1和设备2上。进一步,我们通过数据并行来添加3和设备4,提升系统算力。为了达到这一点,我们对训练数据进行分区(数据分区1和数据分区2),并将模型(算子1和算子2)分配复制到设备3和设备4上生成可以并行执行的程序副本。在前向计算的过程中,设备1和设备3上的算子1副本同时开始,计算结果分别发送(Send)给设备2和设备4完成算子2副本的计算。在反向计算中,设备2和设备4同时开始计算梯度,本地梯度通过Allreduce进行平均。反向计算传递到设备1和设备3上的算子1副本结束。
\ No newline at end of file
+在训练大型人工智能模型中,我们往往会同时面对算力不足和内存不足。因此,我们需要混合使用数据并行和模型并行,这种方法被称为混合并行。 :numref:`ch10-hybrid-parallel`提供了一个由4个设备实现的混合并行的例子。在这个例子中,我们首先实现算子间并行来解决训练程序内存开销过大的问题:该训练程序的算子1和算子2被分摊到了设备1和设备2上。进一步,我们通过数据并行来添加3和设备4,提升系统算力。为了达到这一点,我们对训练数据进行分区(数据分区1和数据分区2),并将模型(算子1和算子2)分配复制到设备3和设备4上生成可以并行执行的程序副本。在前向计算的过程中,设备1和设备3上的算子1副本同时开始,计算结果分别发送(Send)给设备2和设备4完成算子2副本的计算。在反向计算中,设备2和设备4同时开始计算梯度,本地梯度通过Allreduce进行平均。反向计算传递到设备1和设备3上的算子1副本结束。
\ No newline at end of file
diff --git a/chapter_distributed_training/overview.md b/chapter_distributed_training/overview.md
index 0fa27c5..a9e294b 100644
--- a/chapter_distributed_training/overview.md
+++ b/chapter_distributed_training/overview.md
@@ -4,7 +4,7 @@
接下来,我们详细讨论分布式训练系统的设计动机
-
+
:width:`800px`
:label:`ch10-computation-increase`
@@ -12,7 +12,7 @@
单处理器的算力不足是促使人们设计分布式训练系统的一个主要原因。一个处理器的算力可以用**每秒钟浮点数操作**(Floating
Point Operations Per Second,FLOPS)来衡量。
-如:numref:`ch10-computation-increase`所示,根据摩尔定律(Moore's
+如 :numref:`ch10-computation-increase`所示,根据摩尔定律(Moore's
Law),中央处理器的算力每18个月增长2倍。虽然计算加速卡,如GPU和Tensor
Processing
Unit(TPU),针对机器学习计算(如矩阵相乘)提供了大量的算力。这些加速卡的发展最终也受限于摩尔定律,增长速度也停留在每18个月2倍。而与此同时,机器学习模型正在快速发展。短短数年,我们从仅能识别有限物体的AlexNet模型,一路发展到在复杂任务中打败人类的AlphaStar。这期间,模型对于算力需求每18个月增长了35倍。解决处理器性能和算力需求之间的鸿沟
@@ -29,12 +29,12 @@ A100)仅能提供最高80GB的内存。单卡内存空间的增长受到硬件
受限于单节点的有限算力,内存和存储资源,人们把关注投向了日益成熟的云计算数据中心。一个数据中心管理着数十万个计算服务器。随着数据中心的全球部署,人们可以很方便地获得数百个服务器。这些服务器可以通过分布式训练系统来协调和管理,解决训练大型机器学习模型过程遇到的算力,内存和存储不足,从而完成训练过程的加速。
-
+
:width:`800px`
:label:`ch10-single-vs-multi`
在设计分布式训练系统的过程中,我们需要找出有资源瓶颈的计算任务,根据计算任务的特点,将其拆分成多个子任务,然后将子任务分发给多个节点(可以是服务器,机器,或者是加速卡)并行完成。
-:numref:`ch10-single-vs-multi`描述了如何将单节点执行转换为分布式执行的一般过程。在机器学习系统中,一个计算任务往往会有一组数据(例如训练样本)或者任务(例如算子)作为输入,利用一个计算节点(例如GPU)生成一组输出(例如梯度)。假如单节点成为瓶颈,我们可以利用分布式计算进行加速。分布式执行一般具有三个步骤:第一步,我们需要将输入进行**切分**。第二步,每个输入部分会分发给不同的计算节点,实现**并行**计算。第三步,每个计算节点的输出,进一步**合并**,最终得到和单节点等价的计算结果。这种切分-并行-合并的模式,本质上实现了分而治之算法(Divide-and-Conquer
+ :numref:`ch10-single-vs-multi`描述了如何将单节点执行转换为分布式执行的一般过程。在机器学习系统中,一个计算任务往往会有一组数据(例如训练样本)或者任务(例如算子)作为输入,利用一个计算节点(例如GPU)生成一组输出(例如梯度)。假如单节点成为瓶颈,我们可以利用分布式计算进行加速。分布式执行一般具有三个步骤:第一步,我们需要将输入进行**切分**。第二步,每个输入部分会分发给不同的计算节点,实现**并行**计算。第三步,每个计算节点的输出,进一步**合并**,最终得到和单节点等价的计算结果。这种切分-并行-合并的模式,本质上实现了分而治之算法(Divide-and-Conquer
Algorithm)的设计思想:由于每个计算节点只需要负责更小的子任务,因此其可以更快速的完成计算,最终形成对整个计算过程的加速。
### 用户益处
diff --git a/chapter_distributed_training/parameter_servers.md b/chapter_distributed_training/parameter_servers.md
index e6bc5d3..1885bae 100644
--- a/chapter_distributed_training/parameter_servers.md
+++ b/chapter_distributed_training/parameter_servers.md
@@ -13,11 +13,11 @@ Perception),训练这种神经网络只需要几个GPU即可。而另一方
feature)和产品特征(Item
feature)构成。这些特征往往是大型向量(Vector)。现代推荐系统需要服务数亿的用户,推荐数以千万的商品。假设用户的特征是1MB,而系统需要服务10亿的用户,那么用户的嵌入表就会有1PB的大小。而这个大小远远超过了一个深度学习服务器所具有的内存。假如我们部署大量的昂贵的深度学习服务器来存储海量嵌入表,那么这些服务器上的加速卡的使用率将会极低,无法实现对于硬件的高效利用。
-
+
:width:`800px`
:label:`ch10-parameter-servers`
-为了解决上述问题,人们往往会在稀疏模型集群中混合部署:训练服务器和参数服务器,从而实现对于计算需求和内存需求分别满足。:numref:`ch10-parameter-servers` 描述了带有参数服务器的机器学习集群。这个集群中含有2个训练服务器和2个参数服务器,训练服务器一般是拥有加速卡的计算优化服务器(Compute-optimised
+为了解决上述问题,人们往往会在稀疏模型集群中混合部署:训练服务器和参数服务器,从而实现对于计算需求和内存需求分别满足。 :numref:`ch10-parameter-servers` 描述了带有参数服务器的机器学习集群。这个集群中含有2个训练服务器和2个参数服务器,训练服务器一般是拥有加速卡的计算优化服务器(Compute-optimised
server)。而参数服务器一般是内存优化服务器(Memory-optimised
server),其的内存大小一般远远大于计算优化服务器。在一个稀疏模型中往往拥有神经网络参数和嵌入表参数。神经网络较小,其可以存储在训练服务器内存中。而嵌入表很大,因此需要存储在额外的参数服务器中。参数服务器一般会按照键-值对(Key-value
pairs)的方式来存储参数。常用的键包括用户名(User ID),产品名(Item
diff --git a/chapter_distributed_training/pipeline.md b/chapter_distributed_training/pipeline.md
index 277f77d..7727cfc 100644
--- a/chapter_distributed_training/pipeline.md
+++ b/chapter_distributed_training/pipeline.md
@@ -5,7 +5,7 @@
然而,当这类系统的运行中,计算图中的下游设备需要长期持续处于空闲状态,等待上游设备的计算完成,才可以开始计算,这极大降低了设备的平均使用率。这种现象被称为模型并行空洞(Model
Parallelism Bubble)。
-
+
:width:`800px`
:label:`ch10-pipeline-parallel`
@@ -14,7 +14,7 @@ Mini-batch)划分为多个微批量(Micro-batch)。假设一个数据小
propagation)和反向传播(Backwards
propagation),计算出梯度。每个微批量对应的梯度将会缓存,等到全部微批量完成,缓存的梯度会被加和,算出平均梯度,更新模型参数。
-:numref:`ch10-pipeline-parallel` 进一步给出了一个流水线并行的执行例子。在本例中,模型参数需要切分给4个设备存储。为了充分利用起来这4个设备,我们将小批量切分为2个微批量。当设备1完成第一个微批量的前向传播后(表示为$F_{0,0}$)后,他会将中间结果发送给设备2,触发响应的前向传播任务(表示为$F_{1,0}$)。与此同时,设备1也可以开始第二个微批量的前向传播任务(表示为$F_{0,1}$)。前向传播会在流水线的最后一个设备--设备3--完成。系统于是开始反向传播。设备4开始第1个微批量的反向传播任务(表示为$B_{3,0}$)。该任务完成后的中间结果会被发送给设备3,触发响应的反向传播任务(表示为$B_{2,0}$)。与此同时,设备4会缓存好对应第1个微批量的梯度,接下来开始第2个微批量计算(表示为$B_{3,1}$)。当设备4完成了全部的反向传播计算后,他会将本地缓存的梯度进行相加,并且除以微批量数量,计算出平均梯度,该梯度用于更新模型参数。
+ :numref:`ch10-pipeline-parallel` 进一步给出了一个流水线并行的执行例子。在本例中,模型参数需要切分给4个设备存储。为了充分利用起来这4个设备,我们将小批量切分为2个微批量。当设备1完成第一个微批量的前向传播后(表示为$F_{0,0}$)后,他会将中间结果发送给设备2,触发响应的前向传播任务(表示为$F_{1,0}$)。与此同时,设备1也可以开始第二个微批量的前向传播任务(表示为$F_{0,1}$)。前向传播会在流水线的最后一个设备--设备3--完成。系统于是开始反向传播。设备4开始第1个微批量的反向传播任务(表示为$B_{3,0}$)。该任务完成后的中间结果会被发送给设备3,触发响应的反向传播任务(表示为$B_{2,0}$)。与此同时,设备4会缓存好对应第1个微批量的梯度,接下来开始第2个微批量计算(表示为$B_{3,1}$)。当设备4完成了全部的反向传播计算后,他会将本地缓存的梯度进行相加,并且除以微批量数量,计算出平均梯度,该梯度用于更新模型参数。
流水线并行的关键因素是流水线泡沫(Bubble)。当设备完成前向传播后,必须等到全部反向传播开发,在此期间设备会处于空闲状态。在 :numref:`ch10-pipeline-parallel` 中,我们可以看到设备1在完成2个前向传播任务后,要等很多时间才能开始2个传向传播任务。这其中的等待时间即被称为泡沫。为了减少设备的等待时间,一种常见的做法是尽可能的增加微批量的数量,从而让反向传播尽可能早的开始。然而,使用非常小的微批量大小,可能会造成加速器无法被充分利用。因此最优的微批量大小是多种因素的折中。其中最核心的因素是流水线泡沫的大小和加速器的计算能力。
diff --git a/img/ch09/ch10-allreduce-process.pdf b/img/ch09/ch10-allreduce-process.pdf
deleted file mode 100644
index 945b686..0000000
Binary files a/img/ch09/ch10-allreduce-process.pdf and /dev/null differ
diff --git a/img/ch09/ch10-allreduce-process.svg b/img/ch09/ch10-allreduce-process.svg
new file mode 100644
index 0000000..cfd6a10
--- /dev/null
+++ b/img/ch09/ch10-allreduce-process.svg
@@ -0,0 +1,1132 @@
+
+
+
+
diff --git a/img/ch09/ch10-allreduce-state.pdf b/img/ch09/ch10-allreduce-state.pdf
deleted file mode 100644
index 9889eab..0000000
Binary files a/img/ch09/ch10-allreduce-state.pdf and /dev/null differ
diff --git a/img/ch09/ch10-allreduce-state.svg b/img/ch09/ch10-allreduce-state.svg
new file mode 100644
index 0000000..2316a94
--- /dev/null
+++ b/img/ch09/ch10-allreduce-state.svg
@@ -0,0 +1,732 @@
+
+
+
+
diff --git a/img/ch09/ch10-averaged-gradient.pdf b/img/ch09/ch10-averaged-gradient.pdf
deleted file mode 100644
index d5480ec..0000000
Binary files a/img/ch09/ch10-averaged-gradient.pdf and /dev/null differ
diff --git a/img/ch09/ch10-averaged-gradient.svg b/img/ch09/ch10-averaged-gradient.svg
new file mode 100644
index 0000000..83c5b9c
--- /dev/null
+++ b/img/ch09/ch10-averaged-gradient.svg
@@ -0,0 +1,435 @@
+
+
+
+
diff --git a/img/ch09/ch10-computation-increase.pdf b/img/ch09/ch10-computation-increase.pdf
deleted file mode 100644
index 978739d..0000000
Binary files a/img/ch09/ch10-computation-increase.pdf and /dev/null differ
diff --git a/img/ch09/ch10-computation-increase.svg b/img/ch09/ch10-computation-increase.svg
new file mode 100644
index 0000000..1f21ebd
--- /dev/null
+++ b/img/ch09/ch10-computation-increase.svg
@@ -0,0 +1,91 @@
+
+
+
+
diff --git a/img/ch09/ch10-data-parallel.pdf b/img/ch09/ch10-data-parallel.pdf
deleted file mode 100644
index af60584..0000000
Binary files a/img/ch09/ch10-data-parallel.pdf and /dev/null differ
diff --git a/img/ch09/ch10-data-parallel.svg b/img/ch09/ch10-data-parallel.svg
new file mode 100644
index 0000000..c89a8a1
--- /dev/null
+++ b/img/ch09/ch10-data-parallel.svg
@@ -0,0 +1,539 @@
+
+
+
+
diff --git a/img/ch09/ch10-datacentre.pdf b/img/ch09/ch10-datacentre.pdf
deleted file mode 100644
index f2f1ea1..0000000
Binary files a/img/ch09/ch10-datacentre.pdf and /dev/null differ
diff --git a/img/ch09/ch10-datacentre.svg b/img/ch09/ch10-datacentre.svg
new file mode 100644
index 0000000..7fa955a
--- /dev/null
+++ b/img/ch09/ch10-datacentre.svg
@@ -0,0 +1,185 @@
+
+
+
+
diff --git a/img/ch09/ch10-hybrid-parallel.pdf b/img/ch09/ch10-hybrid-parallel.pdf
deleted file mode 100644
index 0b853e6..0000000
Binary files a/img/ch09/ch10-hybrid-parallel.pdf and /dev/null differ
diff --git a/img/ch09/ch10-hybrid-parallel.svg b/img/ch09/ch10-hybrid-parallel.svg
new file mode 100644
index 0000000..7c65c21
--- /dev/null
+++ b/img/ch09/ch10-hybrid-parallel.svg
@@ -0,0 +1,560 @@
+
+
+
+
diff --git a/img/ch09/ch10-model-parallel-inter-op.pdf b/img/ch09/ch10-model-parallel-inter-op.pdf
deleted file mode 100644
index ca78652..0000000
Binary files a/img/ch09/ch10-model-parallel-inter-op.pdf and /dev/null differ
diff --git a/img/ch09/ch10-model-parallel-inter-op.svg b/img/ch09/ch10-model-parallel-inter-op.svg
new file mode 100644
index 0000000..2157a97
--- /dev/null
+++ b/img/ch09/ch10-model-parallel-inter-op.svg
@@ -0,0 +1,249 @@
+
+
+
+
diff --git a/img/ch09/ch10-model-parallel-intra-op.pdf b/img/ch09/ch10-model-parallel-intra-op.pdf
deleted file mode 100644
index 26b4d67..0000000
Binary files a/img/ch09/ch10-model-parallel-intra-op.pdf and /dev/null differ
diff --git a/img/ch09/ch10-model-parallel-intra-op.svg b/img/ch09/ch10-model-parallel-intra-op.svg
new file mode 100644
index 0000000..5c567cd
--- /dev/null
+++ b/img/ch09/ch10-model-parallel-intra-op.svg
@@ -0,0 +1,346 @@
+
+
+
+
diff --git a/img/ch09/ch10-parameter-server-replication.pdf b/img/ch09/ch10-parameter-server-replication.pdf
deleted file mode 100644
index 1e17389..0000000
Binary files a/img/ch09/ch10-parameter-server-replication.pdf and /dev/null differ
diff --git a/img/ch09/ch10-parameter-server-replication.svg b/img/ch09/ch10-parameter-server-replication.svg
new file mode 100644
index 0000000..0882492
--- /dev/null
+++ b/img/ch09/ch10-parameter-server-replication.svg
@@ -0,0 +1,224 @@
+
+
+
+
diff --git a/img/ch09/ch10-parameter-servers.pdf b/img/ch09/ch10-parameter-servers.pdf
deleted file mode 100644
index ebeab39..0000000
Binary files a/img/ch09/ch10-parameter-servers.pdf and /dev/null differ
diff --git a/img/ch09/ch10-parameter-servers.svg b/img/ch09/ch10-parameter-servers.svg
new file mode 100644
index 0000000..3b4c2a7
--- /dev/null
+++ b/img/ch09/ch10-parameter-servers.svg
@@ -0,0 +1,202 @@
+
+
+
+
diff --git a/img/ch09/ch10-pipeline-parallel.pdf b/img/ch09/ch10-pipeline-parallel.pdf
deleted file mode 100644
index 43b7fcf..0000000
Binary files a/img/ch09/ch10-pipeline-parallel.pdf and /dev/null differ
diff --git a/img/ch09/ch10-pipeline-parallel.svg b/img/ch09/ch10-pipeline-parallel.svg
new file mode 100644
index 0000000..352cb30
--- /dev/null
+++ b/img/ch09/ch10-pipeline-parallel.svg
@@ -0,0 +1,589 @@
+
+
+
+
diff --git a/img/ch09/ch10-recommendation-model.pdf b/img/ch09/ch10-recommendation-model.pdf
deleted file mode 100644
index 34b8110..0000000
Binary files a/img/ch09/ch10-recommendation-model.pdf and /dev/null differ
diff --git a/img/ch09/ch10-recommendation-model.svg b/img/ch09/ch10-recommendation-model.svg
new file mode 100644
index 0000000..a466238
--- /dev/null
+++ b/img/ch09/ch10-recommendation-model.svg
@@ -0,0 +1,454 @@
+
+
+
+
diff --git a/img/ch09/ch10-single-node.pdf b/img/ch09/ch10-single-node.pdf
deleted file mode 100644
index f495eed..0000000
Binary files a/img/ch09/ch10-single-node.pdf and /dev/null differ
diff --git a/img/ch09/ch10-single-node.svg b/img/ch09/ch10-single-node.svg
new file mode 100644
index 0000000..52c35f8
--- /dev/null
+++ b/img/ch09/ch10-single-node.svg
@@ -0,0 +1,309 @@
+
+
+
+
diff --git a/img/ch09/ch10-single-vs-multi.pdf b/img/ch09/ch10-single-vs-multi.pdf
deleted file mode 100644
index ff42327..0000000
Binary files a/img/ch09/ch10-single-vs-multi.pdf and /dev/null differ
diff --git a/img/ch09/ch10-single-vs-multi.svg b/img/ch09/ch10-single-vs-multi.svg
new file mode 100644
index 0000000..050cbc3
--- /dev/null
+++ b/img/ch09/ch10-single-vs-multi.svg
@@ -0,0 +1,339 @@
+
+
+
+