所有这些问题的根本原因可以归结于数据扭曲。我们想要实现分片的均衡分布,但是两词的历史分片和单词历史分片都不能带来均衡。因此,我们提出了一种混合方法:渐进式分片和动态调整分片大小。 解决方案:渐进式分片(Progressive sharding) 渐进式分片用迭代的方法来解决数据扭曲(skew)问题。在第一次迭代时,我们首先进行单个字的分片,在这一步的分片中只需要对所有分片(shard)的一元语言模型计数进行分割。一元语言模型计数远少于二元语言模型计数。通常情况下这种处理是可以完成预期作用的,但不包含分片极其大的情况。例如,对应于「how to ...」的分片将会被扭曲。为了解决这个问题,我们核查每个分片的尺寸然后仅处理小于某一阈值的分片。
在第二次迭代时,我们使用二个字的分割,即根据二个字的历史来完成对 N-gram 的分布。在这个阶段,我们只需要向二元语言模型(不包括已在第一次迭代中处理的二元语言模型)共享 N-gram 的计数。这些二元语言模型计数的数目远少于整个的二元语言模型计数数目,因此处理起来也更快。正如上面所说,我们依然核查每个分片的尺寸然后仅处理小于某一阈值的分片。所剩下的分片将会在下一次的迭代中通过三个字历史来处理。在大多数情况下,三次迭代已足以满足非常大数据集的需要。
动态调整分片尺寸 在第一次迭代里,我们用了一个足够大的预设数,从而使得大部分的生成分片尺寸很小。每一个分片是由单个 Spark 所完成。在这次迭代中 0-shard 的分片是非常小的尺寸,有很多小分片并不会影响处理效率。在后面的迭代中,分片的数目将由 N—gram 的未处理部分所自动产生。 这些方案能够成功实现归功于 Spark DSL 的灵活性。通过 Hive,开发者们不需要支配这些低级别的运算。 针对训练模型的通用库 根据不同应用环境,怎样使用语言模型呢?每一种应用可能需要不同的数据和配置,因此不同的管道也应运而生。在 Hive 解决方案中,管道的 SQL 部分应用之间是相似的,但在几个地方有不同的单元。相较于重复每一个管道的代码,我们开发了一种可以调用不同管道和不同数据源及配置的普适的 Spark 应用。 基于 Spark 解决问题时,atv,我们也可以自动地在输入配置的基础上,优化应用程序运行的工作流程中的步骤。比如说,直播,如果用户没有明确指出使用熵修剪算法,那么应用程序将会跳过模型重新评估。如果用户在配置中明确指定了计数截止,那么应用程序将会瓦解许多低计数的 N-grams 并以通配符占位符来减少存储。这些优化组合节省了计算资源,同时可以在更短的时间内产生训练好的模型。 Spark 管道与 Hive 管道性能的比较 我们利用以下性能指标比较 Spark 管道与 Hive 管道: CPU 时间:这是从操作系统的角度衡量 CPU 的使用。比如,如果你在 32 核机上使用所有 CPU 的 50%,以每 10 秒处理一个进程,那么你的 CPU 时间将是 32*0.5*160CPU 秒。 CPU 保留时间:这是从资源管理框架的角度衡量 CPU 的保留。举个例子,如果我们在 32 核机上保留 10 秒来运行一个任务,那么 CPU 的保存时间是 32*10=320CPU 秒。CPU 时间与 CPU 保留时间的比例反映出我们是如何实现在集群上保留 CPU 资源的。当精确度达到要求时,相较于 CPU 时间,在运行相同的工作负载的条件下,保存时间可以作为一个更好的测量尺度去比较引擎的执行。比如,如果一个运程需要 1CPU 秒去运行但是必须保存 100CPU 秒,那么在完成同样的工作量时,按照这种度量标准,它就比一个需要 10CPU 秒运行且保存 10CPU 秒的运程效率低。 延迟/屏蔽时间:从结束到结束的工作时间 以下图表总结了 Spark 和 Hive 工作的性能比较结果。注意 Spark 的管道不是 Hive 管道 1:1 的转化。它有许多有助于实现更好的可测量性和执行的定制和优化。 (责任编辑:本港台直播) |