为什么?

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脚本相关推荐

  1. python c#_【分享】C# 调用 Python 脚本, 与 Python 调用 C# 类库

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C# 调用 Python 脚本 操作步骤 1.创建一个控制台程序. O0101_DotNetCallPython. 2.管理 Nuget 程序包,搜索 I ...

  2. Java调用python脚本

    Java调用python脚本 最近也是刚开始学python,所以这里写了一个简单的小方法用Java来调用python脚本.后期再进行更新. 1.Java启动程序的方法 在Java中提供了两种方法来启动 ...

  3. c++中调用python脚本提示 error LNK2001: 无法解析的外部符号 __imp_Py_Initialize等错误的解决方法

    c++中调用python脚本提示 error LNK2001: 无法解析的外部符号 __imp_Py_Initialize等错误的解决方法 时间:2017-05-09 12:32:06阅读:234评论 ...

  4. excel调用python编程-如何在excel中调用python脚本

    如何在excel中调用python脚本 发布时间:2020-07-03 14:15:28 来源:亿速云 阅读:155 如何在excel中调用python脚本?针对这个问题,这篇文章详细介绍了相对应的分 ...

  5. python调用exe程序 传入参数_关于使用c#调用python脚本文件,脚本文件需要传递参数...

    最近工作中需要干这个事,网上搜了搜资料,改了改,基本是这样 建立一个控制台应用程序: 比如 加入我在命令行直接调用python脚本,命令为 y安装python后,添加环境变量,path下面,加入路径. ...

  6. linux下java调用python脚本,java - 在Linux Terminal中以编程方式从Java调用python脚本 - 堆栈内存溢出...

    我正在开发一个Java应用程序,用于检查源文件中的补丁程序(是否存在). 用于检测补丁程序更改的核心逻辑位于python脚本[titled'patch.py​​']中,并且我的Java应用程序与此Py ...

  7. 【Python】如何在Excel中调用Python脚本,实现数据自动化处理

    这次我们会介绍如何使用xlwings将Python和Excel两大数据工具进行集成,更便捷地处理日常工作. 说起Excel,那绝对是数据处理领域王者般的存在,尽管已经诞生三十多年了,现在全球仍有7.5 ...

  8. java代码调用python_java 直接调用python脚本,并传递参数代码实例|chu

    最近陆续用python写了很多文件处理脚本,虽然功能都比较简单 ,但还是感觉到python对文件处理的简洁高效 ,越发觉得java的语法相当的繁琐~ 接到个需求处理ftp数据接口 .所以想把pytho ...

  9. java 调用python脚本过程_通过Java调用Python脚本

    在进行开发的过程中,偶尔会遇到需要使用Java调用Python脚本的时候,毕竟Python在诸如爬虫,以及科学计算等方面具有天然的优势.最近在工作中遇到需要在Java程序中调用已经写好的Python程 ...

最新文章

  1. ros使用QT插件开发
  2. shell获取git最近一次提交信息_Git修改commit提交信息
  3. RealNVP与Glow:流模型的传承与升华
  4. 直播预告 | 亚马逊高级应用科学家熊元骏:人类行为理解研究进展
  5. 【MySQL数据库】一天学完MySQL笔记——纯SQL文档版
  6. Blazor University (2)布局 — 创建 Blazor 布局
  7. cocos2d-x学习笔记之图片分辨率适配
  8. matlab 图像坐标系
  9. [转载]如何做到 jQuery-free?
  10. 第九十八期:TIOBE11月榜单:C、Swift、Go、D与Rust起起伏伏
  11. php mysql 备份还原_PHP执行Mysql数据库的备份和还原
  12. java 唯一id生成算法_唯一ID生成算法剖析
  13. xor(线性基的合并)
  14. R语言模拟:Bias Variance Decomposition
  15. 【数据采集与数据清洗】课堂笔记
  16. 快速获取Excel表格中的所有图片
  17. Windows 10 VMware-workstation 16 Unlock3.0.3 macOS10.15/macOS11.0
  18. ESP32使用MLX90614红外测温传感器
  19. 机器学习基础补习04---凸优化
  20. 2.Java再识:使用MyEclipse开发java程序

热门文章

  1. windows服务安装与卸载工具
  2. (附源码)基于JSP的养老院信息管理系统的设计与实现 毕业设计211141
  3. 微信小程序——如何一键换肤
  4. 杭州/北京内推 | 阿里达摩院生物医学信息处理团队招聘24届春招实习生
  5. MTK平台的LCM驱动移植
  6. 重庆NK十日行-知识点汇总
  7. vue框架搭建前端登录界面
  8. C语言中结构体指针出现重定义,C语言结构体指针中包含结构体指针
  9. Origin如何做单因素方差分析
  10. 艾默生Micromotion质量流量计的应用总结