我不熟悉使用并行处理进行数据分析。我有一个相当大的数组,我想将一个函数应用于所述数组的每个索引。
这是我到目前为止的代码:
import numpy as np
import statsmodels.api as sm
from statsmodels.regression.quantile_regression import QuantReg
import multiprocessing
from functools import partial
def fit_model(data,q):
#data is a 1-D array holding precipitation values
years = np.arange(1895,2018,1)
res = QuantReg(exog=sm.add_constant(years),endog=data).fit(q=q)
pointEstimate = res.params[1] #output slope of quantile q
return pointEstimate
#precipAll is an array of shape (1405*621,123,12) (longitudes*latitudes,years,months)
#find all indices where there is data
nonNaN = np.where(~np.isnan(precipAll[:,0,0]))[0] #481631 indices
month = 4
#holder array for results
asyncResults = np.zeros((precipAll.shape[0])) * np.nan
def saveResult(result,pos):
asyncResults[pos] = result
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=20) #my server has 24 CPUs
for i in nonNaN:
#use partial so I can also pass the index i so the result is
#stored in the expected position
new_callback_function = partial(saveResult, pos=i)
pool.apply_async(fit_model, args=(precipAll[i,:,month],0.9),callback=new_callback_function)
pool.close()
pool.join()
当我运行它时,我花了比我根本不使用多处理时间更长的时间才将其停止。函数fit_model大约为0.02秒,那么与apply_async相关联的突出会导致速度变慢吗?完成此处理后,将数据绘制到地图上时,我需要保持结果的顺序。任何关于我需要改进的地方的想法,将不胜感激!
答案 0 :(得分:0)
如果需要使用多处理模块,则可能需要将更多行一起批处理到分配给工作池的每个任务中。但是,对于您正在做的事情,由于其Ray,我建议您尝试一下efficient handling of large numerical data。
import numpy as np
import statsmodels.api as sm
from statsmodels.regression.quantile_regression import QuantReg
import ray
@ray.remote
def fit_model(precip_all, i, month, q):
data = precip_all[i,:,month]
years = np.arange(1895, 2018, 1)
res = QuantReg(exog=sm.add_constant(years), endog=data).fit(q=q)
pointEstimate = res.params[1]
return pointEstimate
if __name__ == '__main__':
ray.init()
# Create an array and place it in shared memory so that the workers can
# access it (in a read-only fashion) without creating copies.
precip_all = np.zeros((100, 123, 12))
precip_all_id = ray.put(precip_all)
result_ids = []
for i in range(precip_all.shape[0]):
result_ids.append(fit_model.remote(precip_all_id, i, 4, 0.9))
results = np.array(ray.get(result_ids))
一些注释
上面的示例是开箱即用的,但是请注意,我稍微简化了逻辑。特别是,我删除了NaN
的处理。
在具有4个物理核心的笔记本电脑上,这大约需要4秒钟。如果改用20个内核,并使数据增大9000倍,我希望它花费大约7200秒,这是一个相当长的时间。一种加快速度的可能方法是使用更多计算机或在每次对fit_model
的调用中处理多行,以分摊一些开销。
上面的示例实际上将整个precip_all
矩阵传递给每个任务。很好,因为每个fit_model
任务仅具有对存储在共享内存中的矩阵副本的读取访问权限,因此不需要创建自己的本地副本。对ray.put(precip_all)
的调用一次将数组放置在共享内存中。
大约differences between Ray and Python multiprocessing。注意,我正在帮助开发Ray。