c++多线程调用python脚本
为什么?
1、提升效率。
2、一开始代码是在python中用了多进程,后面发现c++调用的Python代码是无法开启多进程的。由于Python解释器有全局解释所GIL的原因,导致在同一时刻只能有一个线程拥有解释器,所以在C++多线程调用python脚本时,需要控制GIL,线程获取GIL。
c++如何开启多线程
首先要引入头文件#include<thread>,管理线程的函数和类在该头文件中声明,其中包括std::thread类。
语句"std::thread th1(test);"创建了一个名为th1的线程。
join()是线程阻塞方法,主函数阻塞直到th1子线程运行完毕。
#include<iostream>
#include<thread>
using namespace std;void test()
{cout << "子线程运行" << endl;cout << "子线程id为" << this_thread::get_id() << endl;
}
int main()
{cout << "主线程" << endl;thread th1(test);cout << "主线程中显示子线程id为" << th1.get_id() << endl;th1.join();return 0;
}
结果:
c++多线程调用python脚本
此处涉及到c++与numpy之间的通信协议。(可以查看我之前写的:https://mp.weixin.qq.com/s/DJCCXXGH_2658p2ytMvZMw)
在C++多线程环境下,直接调用 api操作 Python解释器,肯定会导致 core dump, 因为 Python 绝大部分函数都是非线程安全的。由GIL控制访问顺序。
Python解释器不是完全线程安全的。为了支持多线程Python程序,有一个全局锁,称为 global interpreter lock or GIL,在当前线程能够安全访问Python对象之前,它必须由当前线程持有。没有锁,即使是最简单的操作也可能导致多线程程序中的问题。
话不多说,附上代码。改代码将一个800*512*512的ct图像分别放入4个不同的python线程计算,最后再将运行结果拿回来。
#include<iostream>
#include"include/Python.h"
#include"arrayobject.h"
#include<object.h>
#include<thread>
#include<vector>
using namespace std;
/*
class PythonThreadLocker
{PyGILState_STATE state;
public:PythonThreadLocker() : state(PyGILState_Ensure()){}~PythonThreadLocker() {PyGILState_Release(state);}
};
void NumpyToPtr(PyArrayObject* pRet,short* ptr)
{int layer = pRet->dimensions[0],Rows = pRet->dimensions[1], columns = pRet->dimensions[2];int j = 0;for (int c = 0; c < layer; c++){for (int Index_m = 0; Index_m < Rows; Index_m++) {for (int Index_n = 0; Index_n < columns; Index_n++) {ptr[j] = *(short*)(pRet->data + c* pRet->strides[0]+Index_m * pRet->strides[1] + Index_n * pRet->strides[2]);j++;}}}}
void testmul(short* ptr, npy_intp* dims,short* ptr2, PyObject* times)
{PythonThreadLocker locker;PyObject* pModule = PyImport_ImportModule("mul");PyObject* PyArray = PyArray_SimpleNewFromData(3, dims, NPY_SHORT, ptr);PyObject* pFunc = PyObject_GetAttrString(pModule, "ff");//用tuple装起来PyObject* args = PyTuple_New(2);PyTuple_SetItem(args, 0, PyArray);PyTuple_SetItem(args, 1, times);PyArrayObject* pRet = (PyArrayObject*)PyEval_CallObject(pFunc, args);NumpyToPtr(pRet, ptr2);Py_CLEAR(pModule);Py_CLEAR(PyArray);Py_CLEAR(pFunc);Py_CLEAR(args);Py_CLEAR(pRet);
}
void pythoninit()
{Py_SetPythonHome(L"./");//指定python.exe位置需要修改成自己的 python的环境Py_Initialize();PyEval_InitThreads();//启用线程支持PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('./')");PyRun_SimpleString("import os");PyRun_SimpleString("print(os.listdir())");
}
int main()
{pythoninit();//初始化Numpyimport_array();//造数据short* ptr = new short[800*512*512];for (int i = 0; i < 80 * 512 * 512; i++){ptr[i] = i;}npy_intp dims[3] = { 800,512,512 };vector<short*> returnptr(4);for (int i = 0; i < 4; i++){returnptr[i] = new short[800 * 512 * 512];}Py_BEGIN_ALLOW_THREADS;cout << PyGILState_Check() << endl;thread t1(testmul, ptr, dims, returnptr[0], Py_BuildValue("h", 10));thread t2(testmul, ptr, dims, returnptr[1], Py_BuildValue("h", 20));thread t3(testmul, ptr, dims, returnptr[2], Py_BuildValue("h", 30));thread t4(testmul, ptr, dims, returnptr[3], Py_BuildValue("h", 40));t1.join();t2.join();t3.join();t4.join();Py_END_ALLOW_THREADS;delete[] ptr;for (int i = 0; i < 4; i++){delete[] returnptr[i];}Py_Finalize();return 0;
}
*/
import numpy as np
import time
def ff(data,times):print(data.shape)data = data.reshape(-1)data = np.clip(data,200,3000)data = data.reshape(-1,512,512)time.sleep(times)return data
c++多线程调用python脚本相关推荐
- python c#_【分享】C# 调用 Python 脚本, 与 Python 调用 C# 类库
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C# 调用 Python 脚本 操作步骤 1.创建一个控制台程序. O0101_DotNetCallPython. 2.管理 Nuget 程序包,搜索 I ...
- Java调用python脚本
Java调用python脚本 最近也是刚开始学python,所以这里写了一个简单的小方法用Java来调用python脚本.后期再进行更新. 1.Java启动程序的方法 在Java中提供了两种方法来启动 ...
- c++中调用python脚本提示 error LNK2001: 无法解析的外部符号 __imp_Py_Initialize等错误的解决方法
c++中调用python脚本提示 error LNK2001: 无法解析的外部符号 __imp_Py_Initialize等错误的解决方法 时间:2017-05-09 12:32:06阅读:234评论 ...
- excel调用python编程-如何在excel中调用python脚本
如何在excel中调用python脚本 发布时间:2020-07-03 14:15:28 来源:亿速云 阅读:155 如何在excel中调用python脚本?针对这个问题,这篇文章详细介绍了相对应的分 ...
- python调用exe程序 传入参数_关于使用c#调用python脚本文件,脚本文件需要传递参数...
最近工作中需要干这个事,网上搜了搜资料,改了改,基本是这样 建立一个控制台应用程序: 比如 加入我在命令行直接调用python脚本,命令为 y安装python后,添加环境变量,path下面,加入路径. ...
- linux下java调用python脚本,java - 在Linux Terminal中以编程方式从Java调用python脚本 - 堆栈内存溢出...
我正在开发一个Java应用程序,用于检查源文件中的补丁程序(是否存在). 用于检测补丁程序更改的核心逻辑位于python脚本[titled'patch.py']中,并且我的Java应用程序与此Py ...
- 【Python】如何在Excel中调用Python脚本,实现数据自动化处理
这次我们会介绍如何使用xlwings将Python和Excel两大数据工具进行集成,更便捷地处理日常工作. 说起Excel,那绝对是数据处理领域王者般的存在,尽管已经诞生三十多年了,现在全球仍有7.5 ...
- java代码调用python_java 直接调用python脚本,并传递参数代码实例|chu
最近陆续用python写了很多文件处理脚本,虽然功能都比较简单 ,但还是感觉到python对文件处理的简洁高效 ,越发觉得java的语法相当的繁琐~ 接到个需求处理ftp数据接口 .所以想把pytho ...
- java 调用python脚本过程_通过Java调用Python脚本
在进行开发的过程中,偶尔会遇到需要使用Java调用Python脚本的时候,毕竟Python在诸如爬虫,以及科学计算等方面具有天然的优势.最近在工作中遇到需要在Java程序中调用已经写好的Python程 ...
最新文章
- ros使用QT插件开发
- shell获取git最近一次提交信息_Git修改commit提交信息
- RealNVP与Glow:流模型的传承与升华
- 直播预告 | 亚马逊高级应用科学家熊元骏:人类行为理解研究进展
- 【MySQL数据库】一天学完MySQL笔记——纯SQL文档版
- Blazor University (2)布局 — 创建 Blazor 布局
- cocos2d-x学习笔记之图片分辨率适配
- matlab 图像坐标系
- [转载]如何做到 jQuery-free?
- 第九十八期:TIOBE11月榜单:C、Swift、Go、D与Rust起起伏伏
- php mysql 备份还原_PHP执行Mysql数据库的备份和还原
- java 唯一id生成算法_唯一ID生成算法剖析
- xor(线性基的合并)
- R语言模拟:Bias Variance Decomposition
- 【数据采集与数据清洗】课堂笔记
- 快速获取Excel表格中的所有图片
- Windows 10 VMware-workstation 16 Unlock3.0.3 macOS10.15/macOS11.0
- ESP32使用MLX90614红外测温传感器
- 机器学习基础补习04---凸优化
- 2.Java再识:使用MyEclipse开发java程序