关于机器学习:新生代工程师手把手教你玩转Alluxio+ML上篇

30次阅读

共计 4950 个字符,预计需要花费 13 分钟才能阅读完成。




置信很多人都十分相熟, Alluxio 是能够对各种不同的数据源,包含阿里云、腾讯云的数据进行缓存,以晋升各种训练的性能,它下面包含了像 PyTorch, Tensorflow 等一系列训练的软件。

而 Alluxio 与很多的缓存解决方案的不同点就在于咱们其实是一个分布式缓存,数据如果在一台机子上放不下,咱们把它分到多台机子上,独特为大家提供缓存性能。

同时 Alluxio 提供一个对立的命名空间,来自不同的数据源的数据,都能够在 Alluxio 对立命名空间之下得以展现及应用。所以咱们的各种利用就像应用同一个文件夹外面的文件一样,来应用各种来自不同数据源的数据。

同时,Alluxio 提供多种不同的 API 实用于不同的场景。在咱们的训练场景下,提供了 POSIX API,让训练能够像应用本地文件夹一样去应用咱们的远端数据源。

首先应该如何去部署 Alluxio,倡议把 Alluxio 与咱们的训练尽可能地部署在同一个机房里或者同一个集群中,这样咱们训练读取来自 Alluxio 中的数据会更加的快,训练的 I / O 速度越快,训练性能可能会越好。在其余状况下,如果训练和 Alluxio 部署在同一个机房,甚至同一个地区也有助于咱们对远端数据源进行缓存减速。



Master 其实有几大资源块,其中一个是内存,一个是 CPU。Master 次要是存储元数据的节点,它保留文件的元数据信息,而且 Master 也须要能声援 client worker 所有的连接线程所须要的空间,就是一方面要保留这个元数据信息,另一方面要能声援 client 和 worker 想要取得这种元数据信息的所有的线程资源。

在保留数据信息方面,有两种形式,一方面是 HEAP metastore,元数据是保留在内存当中,而另一方面能够应用 ROCKS off-heap metastore。也就是咱们的元数据不光保留在内存中,也保留在磁盘中,而这种形式是默认配置,并且举荐应用。特地是在海量文件的场景下,元数据的量十分的宏大,而 ROCKS 这种形式,因为磁盘的容量十分的大,其实能够存储更多的元数据,而不必放心 Master 可能存不下的问题。各大科技公司应用 alluxio 进行训练的时候也是设置 ROCKS off-heap metastore。

咱们要反对咱们的客户端以及 worker 节点来向 Master 做索要元数据的各种操作所须要的内存。因为每个线程都是须要占用肯定的内存空间的,在高并发的状况下,可能会有成千上万的并发的连接线程,须要给到足够的空间,以缩小线程池的内存压力,来进步响应速度。而至于须要多少内存,能够通过一个指南,计算所须要的内存空间,然而无奈十分精确地预计大家须要多少的内存空间。倡议设置一个比拟正当的值,比如说 64GB 或者更高的一个值,大家再理论监控内存的应用状况。如果大家发现咱们的内存使用率十分的高,而且频繁 GC,就调大这个数值,而如果咱们发现可能内存设太多了,基本用不到这么多内存,那再把这个数值调小,就是前一两周进行内存的监控,调到一个适合的数值。

另一方面是 Master 端的 CPU 资源,CPU 资源决定 Master 解决并发申请、并行递归操作以及周期性工作的能力。而在海量小文件场景下,Master CPU 其实是决定了咱们能解决多高并发的海量元数据申请。倡议最低要求是 4 个 core,在生产中至多把它打到 16 或者到 32 个 core,能够依据所需元数据的 ops 计算根本配置,并且动静调整。

CPU 资源的监控包含几个方面,一方面能够通过 Master 指标进行监控,能够看有多少申请正在期待解决 Master metrics:RpcQueueLength,就是有多少个申请正在期待被解决,可能 Master 只能解决一秒钟 10 个申请,而你却有一秒钟 20 个申请,那就有 10 个申请在不停地累加到你的解决的期待池中,这样显然是一个不太衰弱的状况。另一方面能够去看 Master 元数据操作到底耗时多少,Master 端的每一个元数据操作,咱们都会对它进行工夫的指标记录。如果这个元数据操作的耗时远远大于业务需要的话,那可能就是存在元数据跟不上需要的状况,可能也来源于 CPU 资源不够的状况。另一方面能够对 RPC 进行一个指标追踪,比如说 Worker RPC 可能一共花了一秒钟,然而在 Master 端可能只花了几十毫秒,剩下的工夫都在期待,那就要想这个期待是来源于网络, 还是来源于 Master CPU 资源的竞争。

提到 worker 内存,worker 会应用 off-heap 来存储 worker 的元数据,所以这方面是无需过多的内存资源。所以咱们认为 worker 的元数据,64 兆基本上入不敷出,然而 worker 之所以须要内存,是因为在 worker 进行传输数据的时候,会耗费大量的 heap 或者 direct memory 资源,其实是会影响到数据传输的并发度的问题。咱们会倡议依据读写并发度确定一个初始值,比方 16GB 和 32GB, 而后像相似监控 master 一样来监控 worker 的内存应用状况并动静调整。

而 worker 的 CPU 也决定 worker 同步解决 I / O 申请的能力。在海量小文件场景下,咱们要确保有足够的 CPU 资源来响应高并发数据申请,特地是每读写一个文件,可能都会发一个 RPC 申请,RPC 申请是须要有足够的 CPU 资源在背地予以撑持的,能够跟着指南计算根本的配置,至多 8 -16 vCore,而后依据监控再动静调整。

Worker 的存储,这次要指的是 Alluxio 用什么样的存储介质以及存储大小来缓存底层存储系统的一些数据,默认是用内存来进行存储的,然而如果是在海量数据的状况下,倡议配置磁盘,用磁盘来进行数据存储更多的数据。

能够通过 Alluxio master 的元数据缓存来缓解底层存储系统的元数据压力,也就是说咱们的利用能够间接来 master 端要元数据,而不须要一次又一次的去存储系统拿数据。很多公司找到 Alluxio,也是因为他们的底层存储系统的元数据压力十分的大,HDFS cluster,ceph 集群齐全不能解决这么高的元数据申请,而应用 master 能够缓解这部分的压力。然而这会波及到一个问题,Alluxio 的元数据跟底层存储系统之间的元数据是否是统一的。为了保障元数据的一致性,一种形式是定期的全局元数据同步,这个是默认的配置。比如说每 30 秒会齐全全局同步一次底层存储系统的元数据操作,而另一方面能够用用户操作来定期促发元数据同步,在每一个用户对一个文件进行操作之前,咱们先看一下对这个文件的上一次元数据同步是什么时候产生的,如果超过了一个指定的数值,就再来一次元数据同步。

如何用 fuse 客户端来二次缓存元数据,缓解 master 节点的元数据压力。

能够通过配置 metadata cache enable 开启元数据缓存,而这个默认是不关上的,能够设置想要缓存多少元数据以及工夫是多少,就十分实用于当咱们训练的时候,对数据一致性要求不会很高,或者在短期内不太在乎元数据扭转的状况,能够把这个缓存给关上,以晋升训练性能。同时还能够进一步应用 fuse 的挂载选项。在操作系统层面对数据集进行进一步的缓存,能够调大一些文件属性,名称查找等操作的零碎缓存工夫。

讲到数据缓存,Alluxio 能够帮忙提前缓存数据以晋升训练性能,而且提前缓存也能够在训练中进行,能够用一键来挂载数据集到 Alluxio 文件系统中,通过一键分布式缓存命令来一键缓存所须要的训练数据,而这种提前缓存也能够通过调整 job worker 的线程池大小减速分布式缓存。

alluxio.job.worker.threadpool.size 这个配置代表说有多少个线程并发缓存数据。在海量小文件的场景下,倡议把这个数字调的比拟大一点,默认是倡议调到 2×core 数目,然而在这种场景下,会发现调到 10×core 数目会有更好的性能体现。大家能够进一步尝试看这个配置对所须要的场景有没有什么帮忙。

数据读减速是应用 Alluxio 缓存数据来减速训练性能。这外面的一个默认假如就是读 Alluxio 缓存的数据是比间接去读底层零碎更快的,如果发现不是,那通常是在 Alluxio 跟底层数据系统部署到同一个集群的状况下,但这种状况咱们认为就没有太多必要去应用 Alluxio 了。

Alluxio 最大的一个 benefit 其实是如果存储系统在远端,而获取数据十分耗时,且对你的存储系统有较大压力的状况下,咱们是倡议应用 Alluxio 来缓存数据,对数据 I / O 进行提速。

数据读最快的形式当然是过程内读,也就是说数据曾经缓存在本地机器上了,而 fuse 是起在 worker 过程中,能够缩小不必要的 RPC 通信,fuse 间接在过程内跟 worker 说要这个数据,而后 worker 间接从本机去拿到数据,给到 fuse 以及再给到利用。如果要配置 fuse on worker 的话,能够去关上 worker 的配置,alluxio.worker.fuse.enabled =true 就能够了。

其次是能够应用独自的 fuse 过程,数据是存在本地机器上的,fuse 是独自的过程, worker 也是独自的过程,在这种状况下,worker 跟 fuse 是离开的能够更加灵便。能够用多个 fuse 的挂载节点,针对不同的场景,读写的不同场景,进行个性化配置以及配置不同的利用权限。在这种状况下,因为 fuse 要跟 worker 进行多一层的 RPC 操作,这可能会带来肯定的性能损耗或者资源损耗,会减少 fuse 和 worker 的 CPU 和内存的资源耗费,但不肯定会影响性能,可能要依据理论利用场景进行抉择。

另一方面也能够通过在本地集群缓存来晋升读速度,可能本地的机器并没有那么多的空间,可能须要把数据缓存在隔壁的机器上,在这种状况下,能够通过本地的集群缓存来晋升速度,而这种读次要受本地的网络 I / O 以及 RPC 的影响,其实次要是本地网络 I / O 的影响,性能必定是快于从近程存储系统中去读取数据的。

最慢的读取形式,当然是 Alluxio 并没有缓存任何的数据,那就不得不从近程的存储系统中把这部分数据读进来再进行缓存,以晋升咱们将来的读取速度。而这部分 UFS 读基本上是受近程网络 I / O 的影响,如果近程 I / O 比较慢的话,这部分可能读的性能会没有那么好。然而当第一次读进来并缓存之后,后续的读取都会立马减速。

讲到其余的一些优化,包含能够去调高线程池的大小,线程池的大小决定了很多元数据,数据操作的并发度,也就会决定训练性能。可能 I / O 的元数据的延时,包含数据的并发,数据的吞吐这样的等等的数据性能,会影响训练性能。通过调高线程池的大小兴许能用更多的线程来并发地执行这些操作以进步性能。这些线程池包含 master、worker 以及用户端的不同的线程池,这些线程池决定有多少个线程来执行操作,以及最多保留多少的线程来执行操作。

有的时候能够针对用户个性,有时候能够缩小不必要的 Alluxio 操作,比如说能够去除向 master 更新文件拜访工夫的元数据操作,能够示意这部分元数据不须要常常去更新这个文件最新拜访工夫是什么时候,这部分剖析并没有用,那就不须要去更新这部分信息,能够大大减少 RPC 的操作。而有的时候数据如果曾经缓存在一个本地集群中,而本地集群的读取性能曾经足够好的状况下,咱们不须要再去促发一个本地的二次缓存,因为可能二次缓存也晋升不了特地多的速度。同时能够减速对底层存储系统的读速度,可能要依据不同的存储系统进行个性化配置,比方要从 s3 中读大量的数据或者元数据,那咱们能够调大 s3 的线程池的大小,从而晋升对 s3 的元数据和数据操作的并发度,以晋升在海量小文件场景下的性能。

大家也看到,整个 Alluxio 的配置调优可能并没有那么简略,它波及到各种各样的不同的问题,如果只是想要简略的实用 Alluxio 的话,齐全能够应用 Fluid 来一键搭建 Alluxio 集群。你只须要定义你想要应用什么样的数据集,Fluid 会帮你去配置 Alluxio 的参数,配置 Alluxio 的资源,搭建整个 Alluxio 集群以及治理这个集群。大家就不须要去思考种种优化,能够先试用一下,而后看 Fluid 搭建的 Alluxio 集群能不能合乎你的性能需求,解决你的问题。如果不能够的话,就看一下所提到的种种优化能不能帮忙晋升 Fluid 性能,以达到现实的训练要求。

正文完
 0