我有一个令人尴尬的并行问题,但一直想知道如何“设计”功能,以便达到最终结果
所以,这是顺序版
def train_weights(Xtr, ztr, Xte, zte):
regr = some_model()
regr.fit(Xtr, ztr)
error = np.mean((regr.predict(Xte) - zte) ** 2)
return regr.coef_, error
rnge = range(z_train.shape[0])
weights = []
errors = []
for i in rnge:
z_dim_tr = z_train[:,i]
z_dim_te = z_test[:, i]
weight, error = train_weights(X_train, z_dim_tr, X_test, z_dim_te)
weights.append(wgts)
errors.append(error)
所以,我只是从矩阵(训练和测试矩阵)切片 然后将其传递给函数.. 注意,输出的顺序是重量列表中的重量指数...对应于特定的“i”并且对于错误是相同的。
我如何并行化这个?
答案 0 :(得分:2)
由于这只是一般的并行处理问题,因此您可以使用Pool
中的multiprocessing.dummy
。
由于我没有您的数据集,所以请考虑以下示例。
import multiprocessing
from multiprocessing.dummy import Pool
def test(args):
a, b = args
return a
data = [
(1, 2),
(2, 3),
(3, 4),
]
pool = Pool(multiprocessing.cpu_count())
results = pool.map(test, data)
pool.close()
pool.join()
for result in results:
print(result)
池会创建一定数量的工作进程(在本例中为multiprocessing.cpu_count()
)。然后,每个工作人员继续执行作业,直到所有作业都已执行。换句话说,map()
在所有作业都已执行时首先返回。
总而言之,上面的例子,当调用map()
时,它返回的结果列表与给定的顺序相同。因此,最后代码打印1
,2
然后3
。
答案 1 :(得分:1)
查看joblib
https://pythonhosted.org/joblib/parallel.html
Joblib提供了一个简单的辅助类来编写并行for循环 使用多处理。核心思想是编写代码 作为生成器表达式执行,并将其转换为并行 计算:
>>> from math import sqrt
>>> [sqrt(i ** 2) for i in range(10)]
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
可以使用以下内容分布在2个CPU上:
>>> from math import sqrt
>>> from joblib import Parallel, delayed
>>> Parallel(n_jobs=2)(delayed(sqrt)(i ** 2) for i in range(10))
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
答案 2 :(得分:1)
这是示例代码:
from concurrent.futures.thread import ThreadPoolExecutor
MAX_WORKERS = 20
def train_weights(Xtr, ztr, Xte, zte):
regr = some_model()
regr.fit(Xtr, ztr)
error = np.mean((regr.predict(Xte) - zte) ** 2)
return regr.coef_, error
def work_done(future):
weights.append(future.result())
rnge = range(z_train.shape[0])
weights = []
errors = []
for i in rnge:
z_dim_tr = z_train[:, i]
z_dim_te = z_test[:, i]
with ThreadPoolExecutor(MAX_WORKERS) as executor:
executor.submit(train_weights, X_train, X_test, Xte, z_dim_te).add_done_callback(work_done)
这里执行程序返回它提交的每个任务的未来。请记住,如果您使用add_done_callback()
完成的任务从线程返回到主线程(这将阻止您的主线程),如果您真的想要真正的并行性,那么您应该等待未来的对象单独。这是代码片段。
futures = []
for i in rnge:
z_dim_tr = z_train[:, i]
z_dim_te = z_test[:, i]
with ThreadPoolExecutor(MAX_WORKERS) as executor:
futures.append(executor.submit(train_weights, X_train, X_test, Xte, z_dim_te))
wait(futures)
for succeded, failed in futures:
# work with your result here
if succeded:
weights.append(succeded.result())
if failed:
errors.append(failed.result())
答案 3 :(得分:0)
这是使用Ray并行化代码的一种方法。使用Ray的一些优点
Ray是用于编写并行和分布式Python的库。
import numpy as np
import ray
ray.init()
z_train = np.random.normal(size=(100, 30))
z_test = np.random.normal(size=(50, 30))
@ray.remote(num_return_vals=2)
def train_weights(ztr, zte):
# Fit model.
predictions = np.random.normal(size=zte.shape[0])
error = np.mean((predictions - zte) ** 2)
coef = np.random.normal()
return coef, error
weight_ids = []
error_ids = []
for i in range(z_train.shape[1]):
z_dim_tr = z_train[:, i]
z_dim_te = z_test[:, i]
weight_id, error_id = train_weights.remote(z_dim_tr, z_dim_te)
weight_ids.append(weight_id)
error_ids.append(error_id)
weights = ray.get(weight_ids)
errors = ray.get(error_ids)
您可以在Ray documentation中阅读更多内容。请注意,我是Ray开发人员之一。