Python下最便利的多线程并行计算黑科技

题注

最近在实验室中为了验证算法的可行性需要测试大量的数据,那么就需要开启黑科技以使用多线程进行并行计算,加速“跑数据”。

最近老板要求我提高速度,但是跑一次数据就需要消耗一天的时间实在不能忍,由于平时使用Python的科学计算进行数据分析,因此本人通过Python的Numpy、SciPy和Pandas等科学计算库进行算法测试与数据统计。

关于大量数据进行计算时的性能优化问题不是本文的主旨,在此只稍作提示,本文主要记录通过最简便的方式使用多线程实现并发算法测试与统计。

通过循环计算处理任务

初级方式

通常 Python 初学者习惯用For循环来实现重复任务,比如下面的方法:

1
2
3
4
5
6
7
LARGE_NUMBER = 10000000000
data = list()
for each in range(0, LARGE_NUMBER):
internal_val = generate_internal_variable()
data.append(do_something(each, internal_val))

save_data_to_database_or_file(data)

进阶方式

初级方式中对数据的处理是没有问题的,唯一要考虑的是 internal_val 变量如果不在循环内变动,那么最好将其放到for循环之外。这样可以避免每次循环中对局部变量重复内存分配,显著提高处理效率。

对简单的任务使用for循环是很不划算的,因为for循环在每次循时都需要分配内存。最好的办法是:

1
2
3
4
5
6
LARGE_NUMBER = 10000000000
val = generate_variable()

data = [do_something(each, val) for each in range(0, LARGE_NUMBER)]

save_data_to_database_or_file(data)

上面的代码简单粗暴,既提高了代码可读性,又大大提高了执行效率,降低了内存使用率,有兴趣的朋友可以在自己的电脑上比较一下。

使用多线程实现并行计算

在很多情况下单次计算任务是独立的,那么使用循环的方式实现功能最多只能占用一个CPU核,这对于当今的多核时代来说简直是犯罪!

最常见的是使用Python的ThreadThreading等多线程库,但是这类库比较底层,需要对原始代码进行不少修改才能正常使用。同时,对于想要定制并发线程数的人来说也比较麻烦。因此,我推荐使用Python中multiprocess库实现该任务,其最大的黑科技点就是该库的便利性核傻瓜性。

传统的多线程实现教程太多了,我就不在这里赘述了,直接上干货!还是接着上文中例子来阐述:

1
2
3
4
5
6
7
8
9
from multiprocess import Pool

LARGE_NUMBER = 10000000000

# pool = Pool(7) 限定线程数为5(推荐为核数-1,给操作系统及其他任务留条活路)
pool = Pool() # 榨干CPU
pool.map(do_something_func, list(range(0, LARGE_NUMBER)))
pool.close()
pool.join()

如此,仅使用几行代码就实现了该功能,同时几乎不用更改原始代码。关于数据保存,我在这里推荐使用数据库,这种可以从根本上避免了同步、死锁等问题,而且可以简化代码。

如果你还是不明白怎么使用,我在下面放了一份完整的案例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from multiprocess import Pool


def job(x):
result = (x - 2) * 100
print(x)
# 可以直接将结果存入数据库,方便后面用来分析代码
# save_to_database(x)

if __name__ == "__main__":
pool = Pool() # 榨干CPU
pool.map(x, list(range(0, 5000)))
pool.close()
pool.join()

以上,为自己做个笔记,为有幸来此的朋友做个交流。