最近做了一个项目。由于涉及到多线程间CPU资源分配以及GPU计算等,导致多个线程间会相互影响。具体原因暂不知,但经过实验分析,发现多进程间相互没有影响。
这篇帖子来记录一下,线程与进程的具体实现以及项目中自己的一些心得。
线程例子
//算法枚举
typedef enum
{
emArithmetic_start,
emArithmetic_Test,//测试
emArithmetic_end,
}emArithmetic_Type;
//线程传入参数
typedef struct ARG
{
int m_GpuMask;//gpu核号
int m_CpuMask;//cpu核号
emArithmetic_Type m_ArcType;//算法类型
};
//获取序号对应掩码
DWORD_PTR getThreadMask(int mask)
{
DWORD_PTR mask1 = 1;
return (mask1 << mask);
}
/*线程主体执行*/
unsigned int __stdcall thread1(void* p)
{
ARG *PA = (ARG*)p;
if (emArithmetic_Test == PA->m_ArcType)
{
//设置gpu
cv::cuda::setDevice(PA->m_GpuMask);
//设置cpu
SetThreadAffinityMask(GetCurrentThread(), getThreadMask(PA->m_CpuMask));
/*禁止并行处理*/
cv::setNumThreads(0);
while (1)
{//循环执行
/*获取当前毫秒数*/
double time = static_cast<double>(cv::getTickCount());
/*执行函数*/
Test(int GpuId);
/*计算运行一次 Test() 函数花费多长时间(单位:ms)*/
time = ((double)cv::getTickCount() - time) / cv::getTickFrequency();
}
}
}
void main()
{
//线程传入参数赋值
ARG m_arg;
m_arg.m_ArcType = emArithmetic_Test;
m_arg.m_CpuMask = 1;//Cpu核号
m_arg.m_GpuMask = 0;//Gpu核号
//线程启动函数
_beginthreadex(NULL, 0, thread1, (LPVOID)&m_arg, NULL, &threaddr);
while (1)
{//主线程若提前消亡,那么子线程也随之消亡
Sleep(1);
} return 1;
}
注意:
- 在实际项目中 涉及两种算法类(opencv +GPU的图像处理)线程,通过 procexp.exe 工具查看实际线程数,发现大于理论要求创建的线程数量。于是使用 cv::setNumThreads(0) 禁止opencv自行创建多余线程;
- 对于子线程创建,主进程在创建时可以传入参数
//参数3 即主线程传入的参数
_beginthreadex(NULL, 0, thread1, (LPVOID)&m_arg, NULL, &threaddr);
//子线程主体将参数赋值即可用
unsigned int __stdcall thread1(void* p)
{
ARG *PA = (ARG*)p;
}
- 线程可指定运行的Cpu(SetThreadAffinityMask)与Gpu核
//设置Gpu核号
cv::cuda::setDevice(PA->m_GpuMask);
//设置Cpu核号-注意参数2的类型
SetThreadAffinityMask(GetCurrentThread(), getThreadMask(PA->m_CpuMask));
- opencv中计算某一段程序所运行的时间
getTickCount()表示的是从某一事件后(比如开机后)系统时钟的嘀嗒数
getTickFrequency()表示的是CPU一秒内的嘀嗒数
/*获取当前毫秒数*/
double time = static_cast<double>(cv::getTickCount());
/*执行某一段程序*/
Test(int GpuId);
/*计算运行一次 Test() 函数花费多长时间(单位:ms)*/
time = ((double)cv::getTickCount() - time) / cv::getTickFrequency();