我已经构建了一个使用多处理并行工作的进程。Python 2.7中的进程;理论上,它在一个拥有大量vCPU的EC2集群上应该工作得很快,但它并没有像我预期的那样扩展。我在一台96 vCPU机器(一个m5.24x大型实例(上运行代码,但当我尝试并行运行90时,并行化的函数在4 vCPU机器上运行大约45分钟,而所有子进程都需要5个多小时才能完成。
我已经考虑过使用Pool函数来摆脱出现的批处理,但是被调用的函数运行大约200个模型,这些模型确实可以运行很长时间(有时会陷入奇怪的优化循环(,所以我有一个额外的进程在后台运行,一旦子进程每10分钟有3个小时的处理器时间,它就会开始向子进程发送软Ctrl+C命令,以确保任何单个子进程的处理不会持续太长时间。
每个运行子进程的vCPU的利用率在40%到99%之间,直到子进程完成。我的问题是,当移动到更大的实例时,为什么多处理不能线性扩展?我保留了5 vCPU可用于运行任何后台进程,所以它不会陷入困境。
from multiprocessing import Process
import datetime
import Prod_Modeling_Pipeline as PMP
import boto3
import pandas
import time
import numpy
import os
#Define locations
bucketName = 'bucketgoeshere'
output_location = '/home/ec2-user/'
#Pull ATM Setter Over
client = boto3.client('s3')
transfer = boto3.s3.transfer.S3Transfer(client=client)
transfer.download_file(bucketName,'Root_Folder/Control_Files/'+'execution_file.csv', output_location+'execution_file.csv')
#Read-in id list
execution_data = pandas.read_csv(output_location+'execution_file.csv')
ids = execution_data['id']
ni = 90
id_row = [['AAA']*ni for _ in xrange(int(numpy.ceil(len(tids)/float(ni))))]
for i in xrange(len(ids)):
id_row[i/ni][i%ni] = ids[i]
Date = datetime.date.today().strftime('%Y-%m-%d')
totalstart = time.time()
for q in xrange(len(tid_row)):
processes = []
for m in xrange(len(tid_row[q])):
temp = tid_row[q]
try:
p = Process(target=PMP.Model_Function, args=(temp[m],Date,'VALIDATION'))
p.start()
processes.append(p)
time.sleep(1)
print("Started "+temp[m]+" as "+str(os.getpid()))
except:
print("Invalid Run")
for p in processes:
p.join()
print(processes)
print (time.time() - totalstart)
我想我现在明白了为什么它不是线性缩放的。这一切都归结为t2 EC2实例和m EC2实例之间的时钟速度。对于较小的实例,最大时钟速度要高得多。。。对于小t2s高达3.3GHz,对于m型实例高达2.5GHz。
(https://aws.amazon.com/ec2/instance-types/)
当您更改为较大的实例类型时,这将限制缩放能力,因为您移动到了较慢的最大时钟速度。
这并不是我上面的全部问题,但它解释了时间增加的一部分原因。
另一部分似乎是由于使用了共享处理器,因此即使EC2应该花费更少的时间,但我所在组织中的其他人正在占用处理能力。不知道如何在公司限制下解决这个问题。