当运行在具有32个CPU核的Databricks集群中时,多进程python模块似乎不能像Spark MLlib预期的那样工作

当运行在具有32个CPU核的Databricks集群中时,多进程python模块似乎不能像Spark MLlib预期的那样工作,python,multithreading,apache-spark,multiprocessing,azure-databricks,Python,Multithreading,Apache Spark,Multiprocessing,Azure Databricks,请注意,由于这篇文章篇幅较长,我建议您查看每个函数的描述。这是因为,这些函数在没有任何错误的情况下成功执行。我只是将它们呈现给读者,让读者大致了解执行的代码。因此,请多关注我的理论部分和问题部分,而不是技术部分 [理论部分-解释情况] 首先,我想指出这是一个与执行时间相关的问题。虽然时间执行是我关心的问题,但所演示的代码工作得非常好 我想听听你对过去几天我在Databricks集群上处理线程和多处理Python模块时遇到的问题的看法,该集群有32个CPU内核。非常简单地说,我创建了一个函数(如下

请注意,由于这篇文章篇幅较长,我建议您查看每个函数的描述。这是因为,这些函数在没有任何错误的情况下成功执行。我只是将它们呈现给读者,让读者大致了解执行的代码。因此,请多关注我的理论部分和问题部分,而不是技术部分

[理论部分-解释情况]

首先,我想指出这是一个与执行时间相关的问题。虽然时间执行是我关心的问题,但所演示的代码工作得非常好

我想听听你对过去几天我在Databricks集群上处理线程多处理Python模块时遇到的问题的看法,该集群有32个CPU内核。非常简单地说,我创建了一个函数(如下所示),它将Spark数据帧作为输入,并训练两个Spark MLlib分类器。在培训之前,使用类似Spark的命令对Spark数据帧进行一些额外的清理和准备。将显示训练和预处理每个spark数据帧所需的时间。该函数包括训练和预处理功能,应用15次(也就是15个不同的spark数据帧)。因此,您可以理解,我使用线程和多处理的目标是一次执行这15个迭代,而不是按顺序(一个接一个)执行。只要想象一下,这15次迭代在不久的将来将变成1500次。因此,这是未来数据规模扩大的一个基准

在继续之前,我想说明一下我在研究线程和多处理时得出的一些结论。基于Brendan Fortuner的这一点,线程主要用于受GIL限制的I/O绑定任务(防止两个线程在同一个程序中同时执行)。另一方面,多处理模块使用进程来加速CPU密集型Python操作,因为它们受益于多核并避免了GIL。因此,尽管我最初创建了一个线程相似的应用程序,同时应用我的函数15次,但由于上面所述的原因,我后来改用了多处理方法

[技术部分]

Spark数据帧

spark_df=pd.DataFrame({'IMEI':[358639059721529','358639059721529','358639059721529','358639059721529','358639059721735','358639059721735','358639059721735','358639059721735','358639059721735','358639059721735','358639059721735'],
“PoweredOn”:[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0],
‘InnerSensorConnected’:[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0],
‘平均内部温度’:[2.5083397819149877,12.76785419845581,2.5431994716326396,2.5875612214156,2.5786447594332143,2.6642078435610212,12.767857551574707,12.767857551574707,2.6131772499486625,2.5172743565284166]
“外部传感器已连接”:[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0],
“室外湿度”:[31.784826,32.784826,33.784826,43.784826,23.784826,54.784826,31.784826,31.784826,31.784826],
“能源消耗”:[70.0,70.0,70.0,70.0,70.0,70.0,70.0,70.0,70.0,70.0,70.0,70.0,70.0],
“DaysDeploymentDate:[10.0,20.0,21.0,31.0,41.0,11.0,19.0,57.0,44.0,141.0],
“标签”:[0,0,1,1,1,0,0,1,1,1]
}
)
spark\u df=spark.createDataFrame(spark\u df)
数据帧的出现只是为了记住所使用的spark数据帧。假设这10行是7000行,2个IMEI实际上是15个唯一的IMEI,因为我告诉过你,我有15个spark数据帧,每个IMEI有1个(['358639059721529','358639059721735'])

*[应用的功能]

def training\u models\u operation\u multiprocess(资产id、位置、资产总数、时间戳\u snap、连接的\u spark\u数据集):
#-------------------------------------------------------------------------------------------------------------------------
#关键词初始化
#-------------------------------------------------------------------------------------------------------------------------
设备长度=整数(资产总数)
列表\字符串\输出=列表()
最大工人数=16*2
培训比例=0.5
测试分割比率=0.5
交叉验证轮数=2
优化\u metric=“ROC\u AUC”
功能\u列\u name=“功能”
禁用_logging_value=1#一个阻止在应用程序细节中记录标准输出的值
logger_initialization=实例化_logger(插装_键_值)#记录器实例
#时间格式
日期格式=“%Y-%m-%d%H-%m-%S”
#-------------------------------------------------------------------------------------------------------------------------
#关键词初始化
#-------------------------------------------------------------------------------------------------------------------------
尝试:
打印(“{0}:资产ID{1}:{2}/{3}的开始执行计划”。格式(datetime.utcnow().strftime(date\u格式)、资产ID、位置、设备长度)
begin\u time\u 0=time.time()
#1.1筛选与当前资产相关的行
begin\u time\u 1=time.time()
过滤的\u数据集=联接的\u spark\u数据集。其中(联接的\u spark\u数据集.IMEI.isin([asset\u id]))
过滤的\u数据集=应用\u重新分区(过滤的\u数据集,最大\u工作者)
end\u time\u 1=time.time()-begin\u time\u 1
list_string_outputs.append(“{0}:完成步骤1.1资产id{1}:{2}/{3}在:{4}\n.格式(datetime.utcnow().strftim