跨服务器分布式训练实际使用率低

跨服务器分布式训练实际使用率低,第1张

服务器分布式训练是一种利用多台服务器协同训练深度神经网络模型的方法,可以显著提高模型的训练速度和准确率,但在实际使用中使用率低可能有以下原因:
1 服务器配置不均:分布式训练需要多台服务器协同工作,如果服务器配置不均,性能较差的服务器很容易成为瓶颈,导致整个训练过程的效率低下。
2 网络带宽不足:分布式训练需要多台服务器之间频繁传输大量数据,如果网络带宽不足,会导致数据传输速度慢,增加训练的时间和延迟。
3 算法支持不足:一些深度学习算法没有很好地支持分布式训练,导致训练效果不佳,或者需要付出额外的开发代价来实现分布式训练。
4 管理和调度困难:跨服务器分布式训练需要对多台服务器进行管理和任务调度,如果管理和调度不当,会导致训练效率低下或任务出现错误。

torch模型下mobilenet需要训练多久08-模型加速之轻量化模型(二) 深度可分离:MobileNet
时间:2022-11-14
本文章向大家介绍08-模型加速之轻量化模型(二) 深度可分离:MobileNet,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
SqueezeNet虽在一定程度上减少了卷积计算量,但仍然使用传统的卷积计算方式,而在其后的MobileNet利用了更为高效的深度可分离卷积的方式,进一步加速了卷积网络在移动端的应用。
为了更好地理解深度可分离卷积,在本节首先回顾标准的卷积计算过程,然后详细讲解深度可分离卷积过程,以及基于此结构的两个网络结构MobileNet v1与MobileNet v2。
1)标准卷积
假设当前特征图大小为Ci×H×W,需要输出的特征图大小为Co ×H×W,卷积核大小为3×3,Padding为1,则标准卷积的计算过程如图75所示。
标准卷积的过程如下:
·对于输入特征图的左上Ci×3×3特征,利用Ci×3×3大小的卷积核进行点乘并求和,得到输出特征图中一个通道上的左上点,这一步 *** 作的计算量为Ci×3×3。
·在输入特征图上进行滑窗,重复第一步 *** 作,最终得到输出特征图中一个通道的H×W大小的输出,总计算量为Ci×3×3×H×W。这一步完成了图75中一个通道的过程。
·利用Co个上述大小的卷积核,重复第一步过程,最终得到Co ×H×W大小的特征图。
在整个标准卷积计算过程中,所需的卷积核参数量为Ci×3×3×Co,总的计算量如式(7-1)所示。
需要注意,这里的计算量仅仅是指乘法 *** 作,而没有将加法计算在内。
2)深度可分离卷积
标准卷积在卷积时,同时考虑了图像的区域与通道信息,那么为什么不能分开考虑区域与通道呢?基于此想法,诞生了深度可分离卷积(Depthwise Separable Convolution),将卷积的过程分为逐通道卷积与逐点1×1卷积两步。虽然深度可分离卷

一、模型加载
用已经训练好的模型来检测,rcnn_model_file指模型路径。
二、候选区域提取(Region proposals)
本论文采用selective search[3]方法生成候选区域,代码作者以给出,rcnn代码中的selective_search_boxesm是根据selective search源代码中的demom修改的,参数im是矩阵图,不是路径,最后输出格式为N 4的矩阵,N表示region proposals 的个数,每行表示一个region proposal对角线坐标。
三、特征提取(Feature extraction)
使用rcnn_features为每一个region proposals提取cnn特征,输出结果为N 4096,每行表示一个region proposal的特征。
四、分类(classification)
调用下面函数为每一个region proposal计算各类的score,结果为N C 矩阵,C表示物体类别个数,每行表示一个region proposal对应各个类别的score。

您好,学习机器视觉不一定需要有服务器,但是对于大规模的数据处理和模型训练,服务器可以提供更好的计算性能和存储资源,从而加快学习速度和提高模型的准确性。
在学习机器视觉的过程中,需要大量的数据集和算力来训练模型。如果使用个人电脑进行训练,可能会面临计算速度慢、内存不足等问题,而服务器可以提供更好的硬件资源来支持数据处理和模型训练。
另外,服务器还可以提供更好的数据安全性和可靠性。如果将数据存储在个人电脑中,可能会面临数据丢失或泄露的风险,而服务器可以提供更好的数据备份和安全措施,保障数据的安全性和可靠性。
综上所述,学习机器视觉不一定需要有服务器,但是服务器可以提供更好的计算性能、存储资源、数据安全性和可靠性,从而提高学习效率和保障数据安全。

服务程序最为关键的设计是并发服务模型,当前有以下几种典型的模型:
- 单进程服务,使用非阻塞IO
使用一个进程服务多个客户,通常与客户通信的套接字设置为非阻塞的,阻塞只发生在select()、poll()、epoll_wait()等系统调用上面。这是一种行之有效的单进程状态机式服务方式,已被广泛采用。
缺点是它无法利用SMP(对称多处理器)的优势,除非启动多个进程。此外,它尝试就绪的IO文件描述符后,立即从系统调用返回,这会导致大量的系统调用发生,尤其是在较慢的字节传输时。
select()本身的实现也是有局限的:能打开的文件描述符最多不能超过FD_SETSIZE,很容易耗尽;每次从select()返回的描述符组中扫描就绪的描述符需要时间,如果就绪的描述符在末尾时更是如此(epoll特别彻底修复了这个问题)。
- 多进程服务,使用阻塞IO
也称作 accept/fork 模型,每当有客户连线时产生一个新的进程为之服务。这种方式有时是必要的,比如可以通过 *** 作系统获得良好的内存保护,可以以不同的用户身份运行程序,可以让服务运行在不同的目录下面。但是它的缺点也很明显:进程比较占资源,进程切换开销太大,共享某些信息比较麻烦。Apache 13就使用了这种模型,MaxClients数很容易就可以达到。
- 多线程服务,使用阻塞IO
也称之 accept/pthread_create模型,有新客户来时创建一个服务线程而不是服务进程。这解决了多进程服务的一些问题,比如它占用资源少,信息共享方便。但是麻烦在于线程仍有可能消耗光,线程切换也需要开销。
- 混合服务方式
所谓的混合服务方式,以打破服务方和客户方之间严格的1:1关系。基本做法是:
新客户到来时创建新的工作线程,当该工作线程检测到网络IO会有延迟时停止处理过程,返回给Server一个延迟处理状态,同时告诉 Server被延迟的文件描述符,延迟超时时间。Server会在合适的时候返回工作线程继续处理。注意这里的工作线程不是通过 pthread_create()创建的,而是被包装在专门用于处理延迟工作的函数里。
这里还有一个问题,工作线程如何检测网络IO会有延迟?方法有很多,比如设置较短的超时时间调用poll(),或者甚至使用非阻塞IO。如果是套接字,可以设置SO_RCVTIMEO和SO_SNDTIMEO选项,这样更有效率。
除了延迟线程,Server还应提供了未完成线程的支持。
如有有特别耗费时间的 *** 作,你可以在完成部分工作后停止处理,返回给Server一个未完成状态。这样Server会检查工作队列是否有别的线程,如果有则让它们运行,否则让该工作线程继续处理,这可以防止某些线程挨饿。
典型的一个混合服务模型开源实现ServerKit
Serverkit的这些线程支持功能可简化我们的服务程序设计,效率上应该也是有保证的。
2 队列(queue)
ServerKit提供的队列是一个单向链表,队列的存取是原子 *** 作,如果只有一个执行单元建议不要用,因为原子 *** 作的开销较大。
3 堆(heap)
malloc()分配内存有一定的局限,比如在多线程的环境里,需要序列化内存分配 *** 作。ServerKit提供的堆管理函数,可快速分配内存,可有效减少分配内存的序列化 *** 作,堆的大小可动态增长,堆有引用计数,这些特征比较适合多线程环境。目前ServerKit堆的最大局限是分配单元必须是固定大小。
4 日志记录
日志被保存在队列,有一个专门的线程处理队列中的日志记录:它或者调用syslog()写进系统日志,或者通过UDP直接写到远程机器。后者更有效。
5 读写锁
GNU libc也在pthreads库里实现了读写锁,如果定义了__USE_UNIX98就可以使用。不过ServerKit还提供了读写锁互相转换的函数,这使得锁的应用更为d性。比如拥有读锁的若干个线程对同一个hash表进行检索,其中一个线程检索到了数据,此时需要修改它,一种办法是获取写锁,但这会导致释放读锁和获取写锁之间存在时间窗,另一种办法是使用ServerKit提供的函数把读锁转换成写锁,无疑这种方式更有效率。
除了以上这些功能,ServerKit还提供了数据库连接池的管理(当前只支持MySQL)和序列化(Sequences),如感兴趣可参见相关的API文档。
二、ServerKit服务模块编写
ServerKit由3部分组成:server程序,负责加载服务模块、解析配置文件、建立数据库连接池;libserver,动态链接库,提供所有功能的库支持,包括server本身也是调用这个库写的;API,编程接口,你编写的服务模块和ServerKit框架进行对话的接口。
ServerKit需要libConfuse解析配置文件,所以出了安装ServerKit,还需要安装libConfuse。关于libConfuse可参考 >

作为专业人士来说说我了解的“神龙服务器”有多厉害吧。

总体上来说,神龙给我的感觉就是计算届的一个异类,因为它一直在打破常规,不断更新我们的认知。

大家都知道,云计算能够将成千上万台计算机的算力聚合起来,相当于突破了计算机硬件资源的算力和物理堆砌芯片两大瓶颈。神龙的诞生,就是改变了用户在云上获取算力的方式,意味着用户可以直接在云上获取物理机的性能。

不仅如此,阿里云发布的基于神龙云服务器的SCC-GN6,还是业界首个公共云异构超算集群。这个产品同样打破了常规,突破了传统芯片性能的极限,直接推动GPU异构计算进入云超算时代。

通俗一点来说,就是有了基于神龙云服务器的SCC-GN6,就可以为人工智能场景提供高性能计算能力,无人驾驶、智能推荐、机器翻译等都可以从中受益。

基于神龙云服务器的SCC-GN6的出现,还破解了目前单纯堆砌芯片得到的性能已经无法满足企业用户需求的困局。

例如,原本深度学习模型训练需要好几天的时间才能完成,如果在云上构建的异构计算集群,时间就会大大缩短。可以说,在云上构建异构超算集这已经成为企业进行大规模复杂计算任务的最佳选择。

总之,我认为神龙服务器一直在挑战算力的极限,是当下业内非常厉害的产品。

搭建深度学习后台服务器

我们的Keras深度学习REST API将能够批量处理图像,扩展到多台机器(包括多台web服务器和Redis实例),并在负载均衡器之后进行循环调度。

为此,我们将使用:

KerasRedis(内存数据结构存储)

Flask (Python的微web框架)

消息队列和消息代理编程范例

本篇文章的整体思路如下:

我们将首先简要讨论Redis数据存储,以及如何使用它促进消息队列和消息代理。然后,我们将通过安装所需的Python包来配置Python开发环境,以构建我们的Keras深度学习REST API。一旦配置了开发环境,就可以使用Flask web框架实现实际的Keras深度学习REST API。在实现之后,我们将启动Redis和Flask服务器,然后使用cURL和Python向我们的深度学习API端点提交推理请求。最后,我们将以对构建自己的深度学习REST API时应该牢记的注意事项的简短讨论结束。

第一部分:简要介绍Redis如何作为REST API消息代理/消息队列

1:Redis可以用作我们深度学习REST API的消息代理/消息队列

Redis是内存中的数据存储。它不同于简单的键/值存储(比如memcached),因为它可以存储实际的数据结构。今天我们将使用Redis作为消息代理/消息队列。这包括:

在我们的机器上运行Redis

将数据(图像)按照队列的方式用Redis存储,并依次由我们的REST API处理

为新批输入图像循环访问Redis

对图像进行分类并将结果返回给客户端

文章中对Redis官网有一个超链接(>

第二部分:安装和配置Redis

官网做法,linux系统的安装:

自己的安装方法:

conda install redis

开启方式相同:

resdis-server

结果:

测试和原文的命令一致。


第三部分:配置Python开发环境以构建Keras REST API

文章中说需要创建新的虚拟环境来防止影响系统级别的python项目(但是我没有创建),但是还是需要安装rest api所需要依赖的包。以下为所需要的包。


第四部分:实现可扩展的Keras REST API

首先是Keras Redis Flask REST API数据流程图

让我们开始构建我们的服务器脚本。为了方便起见,我在一个文件中实现了服务器,但是它可以按照您认为合适的方式模块化。为了获得最好的结果和避免复制/粘贴错误,我建议您使用本文的“下载”部分来获取相关的脚本和图像。

为了简单起见,我们将在ImageNet数据集上使用ResNet预训练。我将指出在哪里可以用你自己的模型交换ResNet。flask模块包含flask库(用于构建web API)。redis模块将使我们能够与redis数据存储接口。从这里开始,让我们初始化将在run_keras_serverpy中使用的常量


我们将向服务器传递float32图像,尺寸为224 x 224,包含3个通道。我们的服务器可以处理一个BATCH_SIZE = 32。如果您的生产系统上有GPU(s),那么您需要调优BATCH_SIZE以获得最佳性能。我发现将SERVER_SLEEP和CLIENT_SLEEP设置为025秒(服务器和客户端在再次轮询Redis之前分别暂停的时间)在大多数系统上都可以很好地工作。如果您正在构建一个生产系统,那么一定要调整这些常量。

让我们启动我们的Flask app和Redis服务器:


在这里你可以看到启动Flask是多么容易。在运行这个服务器脚本之前,我假设Redis服务器正在运行(之前的redis-server)。我们的Python脚本连接到本地主机6379端口(Redis的默认主机和端口值)上的Redis存储。不要忘记将全局Keras模型初始化为None。接下来我们来处理图像的序列化:


Redis将充当服务器上的临时数据存储。图像将通过诸如cURL、Python脚本甚至是移动应用程序等各种方法进入服务器,而且,图像只能每隔一段时间(几个小时或几天)或者以很高的速率(每秒几次)进入服务器。我们需要把图像放在某个地方,因为它们在被处理前排队。我们的Redis存储将作为临时存储。

为了将图像存储在Redis中,需要对它们进行序列化。由于图像只是数字数组,我们可以使用base64编码来序列化图像。使用base64编码还有一个额外的好处,即允许我们使用JSON存储图像的附加属性。

base64_encode_image函数处理序列化。类似地,在通过模型传递图像之前,我们需要反序列化图像。这由base64_decode_image函数处理。

预处理


我已经定义了一个prepare_image函数,它使用Keras中的ResNet50实现对输入图像进行预处理,以便进行分类。在使用您自己的模型时,我建议修改此函数,以执行所需的预处理、缩放或规范化。

从那里我们将定义我们的分类方法


classify_process函数将在它自己的线程中启动,我们将在下面的__main__中看到这一点。该函数将从Redis服务器轮询图像批次,对图像进行分类,并将结果返回给客户端。

在model = ResNet50(weights="imagenet")这一行中,我将这个 *** 作与终端打印消息连接起来——根据Keras模型的大小,加载是即时的,或者需要几秒钟。

加载模型只在启动这个线程时发生一次——如果每次我们想要处理一个映像时都必须加载模型,那么速度会非常慢,而且由于内存耗尽可能导致服务器崩溃。

加载模型后,这个线程将不断轮询新的图像,然后将它们分类(注意这部分代码应该时尚一部分的继续)


在这里,我们首先使用Redis数据库的lrange函数从队列(第79行)中获取最多的BATCH_SIZE图像。

从那里我们初始化imageIDs和批处理(第80和81行),并开始在第84行开始循环队列。

在循环中,我们首先解码对象并将其反序列化为一个NumPy数组image(第86-88行)。

接下来,在第90-96行中,我们将向批处理添加图像(或者如果批处理当前为None,我们将该批处理设置为当前图像)。

我们还将图像的id附加到imageIDs(第99行)。

让我们完成循环和函数

在这个代码块中,我们检查批处理中是否有图像(第102行)。如果我们有一批图像,我们通过模型(第105行)对整个批进行预测。从那里,我们循环一个图像和相应的预测结果(110-122行)。这些行向输出列表追加标签和概率,然后使用imageID将输出存储在Redis数据库中(第116-122行)。

我们使用第125行上的ltrim从队列中删除了刚刚分类的图像集。最后,我们将睡眠设置为SERVER_SLEEP时间并等待下一批图像进行分类。下面我们来处理/predict我们的REST API端点


稍后您将看到,当我们发布到REST API时,我们将使用/predict端点。当然,我们的服务器可能有多个端点。我们使用@app。路由修饰符以第130行所示的格式在函数上方定义端点,以便Flask知道调用什么函数。我们可以很容易地得到另一个使用AlexNet而不是ResNet的端点,我们可以用类似的方式定义具有关联函数的端点。你懂的,但就我们今天的目的而言,我们只有一个端点叫做/predict。

我们在第131行定义的predict方法将处理对服务器的POST请求。这个函数的目标是构建JSON数据,并将其发送回客户机。如果POST数据包含图像(第137和138行),我们将图像转换为PIL/Pillow格式,并对其进行预处理(第141-143行)。

在开发这个脚本时,我花了大量时间调试我的序列化和反序列化函数,结果发现我需要第147行将数组转换为C-contiguous排序(您可以在这里了解更多)。老实说,这是一个相当大的麻烦事,但我希望它能帮助你站起来,快速跑。

如果您想知道在第99行中提到的id,那么实际上是使用uuid(通用唯一标识符)在第151行生成的。我们使用UUID来防止hash/key冲突。

接下来,我们将图像的id和base64编码附加到d字典中。使用rpush(第153行)将这个JSON数据推送到Redis db非常简单。

让我们轮询服务器以返回预测

我们将持续循环,直到模型服务器返回输出预测。我们开始一个无限循环,试图得到157-159条预测线。从这里,如果输出包含预测,我们将对结果进行反序列化,并将结果添加到将返回给客户机的数据中。我们还从db中删除了结果(因为我们已经从数据库中提取了结果,不再需要将它们存储在数据库中),并跳出了循环(第163-172行)。

否则,我们没有任何预测,我们需要睡觉,继续投票(第176行)。如果我们到达第179行,我们已经成功地得到了我们的预测。在本例中,我们向客户机数据添加True的成功值(第179行)。注意:对于这个示例脚本,我没有在上面的循环中添加超时逻辑,这在理想情况下会为数据添加一个False的成功值。我将由您来处理和实现。最后我们称烧瓶。jsonify对数据,并将其返回给客户端(第182行)。这就完成了我们的预测函数。

为了演示我们的Keras REST API,我们需要一个__main__函数来实际启动服务器

第186-196行定义了__main__函数,它将启动classify_process线程(第190-192行)并运行Flask应用程序(第196行)。

第五部分:启动可伸缩的Keras REST API

要测试我们的Keras深度学习REST API,请确保使用本文的“下载”部分下载源代码示例图像。从这里,让我们启动Redis服务器,如果它还没有运行:

redis-server

然后,在另一个终端中,让我们启动REST API Flask服务器:

python run_keras_serverpy

另外,我建议在向服务器提交请求之前,等待您的模型完全加载到内存中。现在我们可以继续使用cURL和Python测试服务器。

第七部分:使用cURL访问Keras REST API

使用cURL来测试我们的Keras REST API服务器。这是我的家庭小猎犬Jemma。根据我们的ResNet模型,她被归类为一只拥有946%自信的小猎犬。

curl -X POST -F image=@jemmapng ''

你会在你的终端收到JSON格式的预测:

{"predictions": [{"label": "beagle","probability": 09461546540260315},{"label": "bluetick","probability": 0031958919018507004},{"label": "redbone","probability": 0006617196369916201},{"label": "Walker_hound","probability": 00033879687543958426},{"label": "Greater_Swiss_Mountain_dog","probability": 00025766862090677023}],"success": true}

第六部分:使用Python向Keras REST API提交请求

如您所见,使用cURL验证非常简单。现在,让我们构建一个Python脚本,该脚本将发布图像并以编程方式解析返回的JSON。

让我们回顾一下simple_requestpy

# import the necessary packagesimport requests# initialize the Keras REST API endpoint URL along with the input# image pathKERAS_REST_API_URL = ""

我们在这个脚本中使用Python请求来处理向服务器提交数据。我们的服务器运行在本地主机上,可以通过端口5000访问端点/predict,这是KERAS_REST_API_URL变量(第6行)指定的。

我们还定义了IMAGE_PATH(第7行)。png与我们的脚本在同一个目录中。如果您想测试其他图像,请确保指定到您的输入图像的完整路径。

让我们加载图像并发送到服务器:

# load the input image and construct the payload for the requestimage = open(IMAGE_PATH, "rb")read()payload = {"image": image}# submit the requestr = requestspost(KERAS_REST_API_URL, files=payload)json()# ensure the request was sucessfulif r["success"]: # loop over the predictions and display them for (i, result) in enumerate(r["predictions"]): print("{} {}: {:4f}"format(i + 1, result["label"], result["probability"]))# otherwise, the request failedelse: print("Request failed")

我们在第10行以二进制模式读取图像并将其放入有效负载字典。负载通过请求发送到服务器。在第14行发布。如果我们得到一个成功消息,我们可以循环预测并将它们打印到终端。我使这个脚本很简单,但是如果你想变得更有趣,你也可以使用OpenCV在图像上绘制最高的预测文本。

第七部分:运行简单的请求脚本

编写脚本很容易。打开终端并执行以下命令(当然,前提是我们的Flask服务器和Redis服务器都在运行)。

python simple_requestpy

使用Python以编程方式使用我们的Keras深度学习REST API的结果

第八部分:扩展深度学习REST API时的注意事项

如果您预期在深度学习REST API上有较长一段时间的高负载,那么您可能需要考虑一种负载平衡算法,例如循环调度,以帮助在多个GPU机器和Redis服务器之间平均分配请求。

记住,Redis是内存中的数据存储,所以我们只能在队列中存储可用内存中的尽可能多的图像。

使用float32数据类型的单个224 x 224 x 3图像将消耗602112字节的内存。

在训练EfficientNet模型时,选择哪个电脑最快要依赖多个因素,包括模型的大小、数据集的大小和计算设备等。下面列出可能对模型训练速度产生影响的几个因素:
1 GPU:通常来说,使用一块高性能的图形处理器(GPU)是训练大型神经网络的最佳选择。NVIDIA的GPU在深度学习应用方面是公认最优秀的。
2 CPU:如果您不拥有强大的GPU,则选择一台拥有大量的CPU内核的电脑通常也可以提高模型训练速度。一些Intel或AMD的高端桌面处理器、服务器级别的CPU等都是不错的选择。
3 分布式训练:使用多台计算机共同进行模型训练可以显著地提高其训练速度,这一技术被称为分布式训练。由于模型的内存需求通常很高,因此使用GPU控制多台计算机之间的通信,以实现效率的最大化。
总之,在选择可用计算机时,您需要考虑到自身的需求和财力bud定,以及对于训练效率和所需时间量的期望。之后,具体的硬件配置决策还需要参考相关的技术资源和权威机构的建议,以获得适合自己的性价比最佳的训练环境。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/12975930.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-29
下一篇 2023-05-29

发表评论

登录后才能评论

评论列表(0条)

保存