DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

为什么?

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;
 
}
 
 

结果:

1e3495427e222181318eeaacab348e7a.png

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();
 
//初始化Numpy
 
import_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
 
 
 
posted on   DoubleLi  阅读(321)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2019-01-30 双网卡单IP实现网卡冗余与负载均衡
2018-01-30 live555源码分析----RSTPServer创建过程分析
点击右上角即可分享
微信分享提示