默认用boost python包裹的C++对象是不支持pickle的,如果要用pickle.dumps(obj)的话那会提示错误 Pickling of "xxx" instances is not enabled. 这边吐槽一下在最新的代码里,给的reference链接其实还是不可用的。真正正确的是https://www.boost.org/doc/libs/1_74_0/libs/python/doc/html/reference/topics/pickle_support.html。 让你的class支持Pickle协议 若要让你的C++ Class支持Pickle协议,比较“正统”的方法是利用boost提供的boost::python::pickle_suite. 拿代码说话: struct world_t { world_t(const string& country) { … } }; struct world_pickle_suite : boost::python::pickle_suite { static boost::python::tuple getinitargs(const world_t& w) { // [可选实现] 返回一个boost::python::tuple元组,其值被用来构造 // 如果一个类的构造函数**不需要参数**的话,可以不用重载这个方法。 return boost::python::make_tuple(w.country()); } static boost::python::tuple getstate(const world_t& w) { // [可选实现] 如果对象的构造函数并不能完全恢复对象的状态, // 那么要用此函数返回其状态值 }… Continue reading Boost Python的C++对象, Pickle支持及其原理
Category: Python
记录一下找了半天的huge page坑——fork越来越慢的原因
背景 之前发现Jupyter Notebook下面,如果数据占用多的话,开多进程池会特别的慢。一开始以为是Python的锅,但是把multiprocessing.pool改成直接用os.fork()调用以后,问题依旧。照理来说unix下面使用fork开进程,会启用copy-on-write机制,内存增长并不是特别明显,但是实际在htop下面看内存仍然会在fork之后增长,并且和进程数量是线性相关的。 原因 随后想了老半天,想到了可能和页表有关系。查了一下,跑的服务器上huge page确实被禁用了(不知为何…). fork的机制简单地说,是在创建新进程的时候把老的进程控制块(Process Control Block)里内存页表拷贝给了新的PCB——这边具体内存的信息是不拷贝的。由于当时Notebook跑的数据处理任务,里面已经用了不少内存(100GB+),所以拷贝的时候如果用默认的4KB内存页,将会有100 * 1024 * 1024 / 4 = 104,857,600个页表! 按典型一个页表项(Page Table Entry)大小4Bytes计算,一个进程开出来光页表会耗400MB内存.
Python multiprocessing RawArray no disk space, or very slow
It seems that Python writes to /tmp on linux base os when allocating python.multiprocessing.sharedctypes.RawArray. If the disk space on that path is not sufficient, “no disk space” error occurs.The solution is to change the default TMPDIR environment, using one of below methods: bash: export TMPDIR=’/the/new/path’ bash: TMPDIR=/the/new/path python3 your_script.py python: os.environ[‘TMPDIR’]=’/your/new/path’ By the way, using… Continue reading Python multiprocessing RawArray no disk space, or very slow
Python multiprocessing 并行化原则
处理multiprocessing解决棘手的并行问题时,遵循以下策略: 把工作拆分成独立单元; 如果每项工作所花的时间是可变的,那就考虑随机化工作的序列; 对工作队列进行排序,首先处理最慢的任务可能是一个最有用的策略(平均而言); 对于细小琐碎的任务,考虑将他们合并分块(chunk),这样能有效减小fork/join通信开销; 让任务数量与物理CPU数量保持一致; 部分摘自 <High Performance Python> (by Micha Gorelick, Ian Ozsvald)
pyprof2calltree — Python 性能分析 可视化
性能分析用cProfile python -m cProfile -o output.perf your_script.py –your args 然后可以安装pyprof2calltree pyprof2calltree -i output.perf -k 记得系统里要装qcallgrind(windows)或者kcallgrind,不然会打不开生成好的log