用python计算邮费考虑是否加急_python多核计算的那些坑和计算效率考量

最近从处理股票日频、分钟频 转到处理tick级别数据,发现单核计算的能力已经跟不上现在的需求。转向在服务器上做并行计算。亲自捣鼓了一圈,总结一下碰到的各种坑,以及性能提升的一些关键点。大体上按照简单到复杂排序,讲干货:

基本配置

服务器centos7 + Mysql提供tick等行情与基本面数据服务 + Python 3.6 【multiprocessing+sqlalchemy+pandas】+ 本地局域网

关于multiprocessing的大大小小坑

1、安装multiprocessing,代码不是

pip install multiprocessing

而是

pip install multiprocess

2、multiprocessing不支持多参数输入,有人用迭代器,但本人感觉不好用,推荐基于multiprocessing的pathos!

from pathos.multiprocessing import ProcessingPool as Pool

pool = Pool(core_nmuber)

result = pool.map(function,[para1,]*core_nmuber,L_para2)

3、区分multiprocessing的同步、异步和阻塞。如果你想阻塞主进程,推荐您首先研究pool.map,本人觉得它是multiprocessing/pathos中最方便的。

import time

def f(x):

for j in range(2):

print(x*x)

time.sleep(1)

pass

return ('it is ',x)

from multiprocessing import Pool

if __name__ == '__main__':

p = Pool(3)

p_return = p.map(f, range(5)) # 三个子进程同时运行0,1,2;然后剩余两个迭代3,4由最先完成的两个子进程来处理

print(p_return)

代码规划注意事项

因为计算量大,一次测试就会等待很久,所以有必要在编写代码时提前布局。

1、 因为multiprocessing默认不实现变量共享,变量共享会比较复杂,潜在的坑肯定不少。所以推荐直接将单核计算的所有函数打包成一个总函数,然后将总函数+各类参数输入到multiprocessing中。

2、multiprocessing的子进程抛出的异常不会自动输出到控制台,需要我们自己捕获异常,输出到控制台或是日志,而且一般计算涉及多个子函数以及多次循环。所以最好给函数增加报错功能以及错误后继续运行的功能。建议以装饰器的方式批量添加【参见下面代码】,而且为需要检测的各个子函数都添加。

import logging

import functools

def create_error_log():

logger = logging.getLogger("error")

logger.setLevel(logging.INFO)

fh = logging.FileHandler("./cal_fun.err")

fmt = "\n[%(asctime)s-%(name)s-%(levelname)s]:%(message)s"

formatter = logging.Formatter(fmt)

fh.setFormatter(formatter)

logger.addHandler(fh)

return logger

def create_normal_logger():

logger = logging.getLogger("cal_fun_logger")

logger.setLevel(logging.INFO)

fh = logging.FileHandler("./cal_fun.log")

fmt = "\n[%(asctime)s-%(name)s-%(levelname)s]:%(message)s"

formatter = logging.Formatter(fmt)

fh.setFormatter(formatter)

logger.addHandler(fh)

return logger

def try_exception_and_log(fn):

@functools.wraps(fn)

def wrapper(*args, **kwargs):

logger_error = create_error_log()

logger_cal_fun = create_normal_logger()

try:

a = fn(*args, **kwargs)

logger_cal_fun.info(f"finished {fn.__name__}")

return a

except Exception as e:

logger_error.exception("[Error in {} ][arg: {}] msg: {}".format(__name__,*args, str(e)))

pass

# raise #报错后继续运行。

return wrapper

@try_exception_and_log

def sun_fun1(t, stockid):

print()

3、务必先单核调试,再多核调试!

4、要注意耗费时间但比较直接简单的代码写法。比如反复读取数据库会耗费很多时间

计算效率的关键点

1、 multiprocessing注意将多次循环均分到各个核心。我曾看到某人写的:最后一个核分配的计算量最重,其他核计算量均匀。结果整个程序多等最后一个苦逼的核心1个小时。

2、网络瓶颈。我所在的局域网大多数都是千兆设备,但测试时发现只有百兆。最后依次排查,发现一个不起眼的交换机惹的祸,另外网线也经常会作祟。

3、linux资源瓶颈:linux系统对文件打开数有默认限制,比如同时打开同一日志文件次数过多,会报错:open so many files。可以在sh脚本或者修改系统文件的方式。 注意:推荐用前者,因为后者数值写太高,会崩溃进不了系统的。崩溃了用‘单用户模式’修改回来。

4、用linux的资源监视器 监测多核计算的性能使用情况

5、数据库优化!!!非常重要 - 相关数据库的索引 - 多核访问是否达到访问限制:最大连接数、最大数据包等的设置 - 检测数据库的性能表现:慢查询日志、当前端口使用情况等。

6、不要反复进行费时的数据库读取操作。相连相近的读取数据最好能合并,然后再在本地内存分别调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值