Python 在pyspark中并发运行for循环,而不是按顺序运行
下面是我在Databricks集群上运行的循环执行:Python 在pyspark中并发运行for循环,而不是按顺序运行,python,apache-spark,for-loop,pyspark,concurrency,Python,Apache Spark,For Loop,Pyspark,Concurrency,下面是我在Databricks集群上运行的循环执行: datalake\u spark\u dataframe\u downsampled=pd.dataframe( {'IMEI':['001','001','001','001','001','001','002','002'], “OuterSensorConnected:[0,0,0,1,0,0,0], “室外湿度”:[31.784826,32.784826,33.784826,43.784826,23.784826,54.784826,
datalake\u spark\u dataframe\u downsampled=pd.dataframe(
{'IMEI':['001','001','001','001','001','001','002','002'],
“OuterSensorConnected:[0,0,0,1,0,0,0],
“室外湿度”:[31.784826,32.784826,33.784826,43.784826,23.784826,54.784826,31.784826],
“能源消耗”:[70,70,70,70,70,70,70,70],
“DaysDeploymentDate:[0,0,1,1,1,1,1],
'label':[0,0,1,1,0,0,0]}
)
datalake\u spark\u dataframe\u downsampled=spark.createDataFrame(datalake\u spark\u dataframe\u downsampled)
#datalake_spark_dataframe_下采样(spark df)的打印模式:
“根
|--IMEI:字符串(nullable=true)
|--OuterSensorConnected:整数(nullable=false)
|--OuterHumidity:float(nullable=true)
|--能量消耗:浮点(可空=真)
|--DaysDeploymentDate:integer(nullable=true)
|--标签:整数(可空=假)”
device_id=datalake_spark_dataframe_downsampled.select(sql_函数.collect_集('IMEI').alias('unique_IMEIS')).collect()[0]['unique_IMEIS']
打印(设备ID)#[“001”、“002”、“030”]30个ID
对于设备中的i\u id:
#过滤的数据集=datalake\u spark\u dataframe\u downsampled.where(datalake\u spark\u dataframe\u downsampled.IMEI.isin([i]))
#上述操作在函数培训\模型\操作\测试()中执行
尝试:
培训、模型、操作、测试(i)datalake\u spark\u dataframe\u downsampled,drop\u columns\u not\u used\u in\u training,training\u split\u ratio\u value,testing\u split\u ratio\u value,mlflow\u文件夹,cross\u validation\u rounds\u value,features\u column\u name\u,optimization\u metric\u value,pretrained\u models\u减一,folder\u name\u减一,timestamp\u快照,instrumentation\u键值,Candition\u资产ID,executor,设备(ID)
例外情况除外,如e:
自定义日志记录函数(“错误”,指令插入键值,“错误异常:{0}”。格式(e))
为了解决这个问题,我附加了一个示例数据,以大致了解我的数据是如何的..并设想存在更多的行和ID。我刚刚创建了一些,只是为了演示
如您所见,这是在使用pyspark运行的Databricks集群中的for循环中的一个简单函数调用。简单地说,我首先创建数据集中存在的唯一ID(IMEI列)列表。这等于30。因此,我使用for循环运行30次迭代。在每次迭代中,我执行以下步骤:
- 过滤与30个资产id中的每一个匹配的datalake_spark_dataframe_downsampled(spark df)的行。例如,假设初始df的40000行中只有140行对应于第一个设备id
- 基于这140行(过滤的_数据集),该函数进行预处理、训练测试分割,并仅为过滤的数据集的行训练两个Spark ML算法
正在开始执行…
-执行id 001的函数
执行完毕 迭代2
正在开始执行…
-执行id 002的功能
执行完毕 我在日志记录中所需的输出(这是我下面打印的内容) 正在开始执行…
-执行id 001的函数
-执行id 002的功能
-执行id 003的功能
-执行id 004的功能
。 . . .
-执行id 030的函数
执行完毕 全部同时(同时)一次 [更新]根据评论的回答(线程模块): “for循环”是线性执行/顺序执行,可以视为单线程执行 如果要同时运行代码,则需要创建多个线程/进程来执行代码 下面是实现多线程的示例。我没有测试代码,但应该可以:)
这是可能的,您需要实现多个threading@RohitNimmala你能不能提供一个在线指南或一个多线程的spark实现。。。我猜你的意思是,这个例子在回答部分提供了一个例子,因为它不适合评论部分,希望它能帮助你。这不应该是一个问题,它与for循环非常相似,除了并发性。这不会有帮助,因为线程是python实现GIL时不是基于纯并发的。。对于这个任务,您应该坚持并发未来或多处理,因为线程是顺序BTS。@ShubhamJain好的,我将测试两种方法。只要我的DataRicks群集启动。所以,根据你的观点,如果你能根据我的问题发布一个同样使用concurrent.futures或multiprocessing的例子,我会觉得这对我很有帮助。在任何情况下,如果我发现一些无法处理的问题,我都会把手弄脏,我会带着结果回来。@ShubhamJain请检查我问题的屏幕截图更新。线程模块工作得很好…我用concur测试了一个相反的执行
#importing threading library
import threading
# Creating a list of threads
thread_list = []
#looping all objects, creating a thread for each element in the loop, and append them to thread_list
for items in device_ids:
thread = threading.Thread(target=training_models_operation_testing,args=(items, datalake_spark_dataframe_downsampled, drop_columns_not_used_in_training,
training_split_ratio_value, testing_split_ratio_value, mlflow_folder,
cross_validation_rounds_value, features_column_name,
optimization_metric_value, pretrained_models_T_minus_one,
folder_name_T_minus_one, timestamp_snap, instrumentation_key_value,
canditate_asset_ids, executor, device_ids,))
thread_list.append(thread)
#Start multi threaded exucution
for thread in thread_list:
thread.start()
#Wait for all threads to finish
for thread in thread_list:
thread.join()
print("Finished executing all threads")