限制OpenMP线程数提速

背景:视频帧序列逐个跑一遍CNN模型,发现CPU被占满了

经过debug发现问题出在torchvision transorms.totensor上

经过搜索,torch在设计多线程加速计算时候会默认占满所有core,因此cpu会飙满,这对别的应用程序速度影响非常大,因此需要控制一下。

解决方法:
1)torch.set_num_threads(1)
手动控制一下torch占用的线程数

2)设置环境变量
export OMP_NUM_THREADS=1 or export MKL_NUM_THREADS=1

但是,开启多个线程去计算理论上是会提升计算效率的,但有没有提升还需要自己去测试。

关于OpenMP

OpenMP (Open Multi-Processing)是一种多线程加速库,OpenMP在一个进程内启动多个线程。默认线程数为CPU实际能同时运行的个数,通常来说是CPU核心个数,如果cpu有Simultaneous multithreading (SMT)特性也可以开启数倍的个数。如果你有一个四核非超线程 CPU,那么OpenMP默认想要启动4个线程。

如果你使用python多进程模块,你有一个四核CPU,你开了四个进程,此时OpenMP函数也会启动4个线程,因此你最终在4核上启动了16个线程。跑是没问题,但是可能由于任务切换导致的开销导致这样做并不高效。

设置OMP_NUM_THREADS=1关闭了OpenMP的多线程,使得python单进程仅跑单线程。

OpenMP does multi-threading within a process, and the default number of threads is typically the number that the CPU can actually run simultaneously. (This is generally the number of CPU cores, or a multiple of that number if the CPU has an SMT feature such as Intel’s Hyper-Threading.) So if you have, for example, a quad-core non-hyperthreaded CPU, OpenMP will want to run 4 threads by default.
When you use Python’s multiprocessing module, your program starts multiple Python processes which can run simultaneously. You can control the number of processes, but often you’ll want it to be the number of CPU cores/threads, e.g. returned by multiprocessing.cpu_count().
So, what happens on that quad-core CPU if you run a multiprocessing program that runs 4 Python processes, and each calls an OpenMP function runs 4 threads? You end up running 16 threads on 4 cores. That’ll work, but not at peak efficiency, since each core will have to spend some time switching between tasks.
Setting OMP_NUM_THREADS=1 basically turns off the OpenMP multi-threading, so each of your Python processes remains single-threaded.
Make sure you’re starting enough Python processes if you do this, though! If you have 4 CPU cores and you only run 2 single-threaded Python processes, you’ll have 2 cores utilized and the other 2 sitting idle. (In this case you might want to set OMP_NUM_THREADS=2.)

跑一个开多进程,同时包含numpy操作的程序,其中numpy矩阵计算会用到多线程加速。
对比了下限制还是放开OMP线程数,可以发现不限制OMP的话CPU占用非常高,导致最后运行时间相比限制OMP慢多了,因此有些场景还是限制一下OMP线程数反而提速很多。CPU占比过高并一定快!

没有设置OMP_NUM_THREADS时,cpu占用情况
在这里插入图片描述
在这里插入图片描述

设置export OMP_NUM_THREADS=1
在这里插入图片描述
在这里插入图片描述

参考文献:
[1] https://jdhao.github.io/2020/07/06/pytorch_set_num_threads/
[2] https://stackoverflow.com/questions/43894608/use-of-omp-num-threads-1-for-python-multiprocessing
[3] https://stackoverflow.com/questions/30791550/limit-number-of-threads-in-numpy

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
OpenMP(Open Multi-Processing)是一种用于并行计算的编程模型,它通过线程并行化来提高程序的运行效率。在OpenMP中,可以使用线程变量(threadprivate)来定义每个线程独有的私有变量。 线程变量允许每个线程在并行区域中拥有自己的私有副本,而不是共享同一个全局变量。这样可以避免由于多个线程同时访问同一个全局变量而导致的据竞争和错误。 通过在变量声明前添加`threadprivate`关键字,可以将该变量定义为线程变量。例如: ```cpp #pragma omp threadprivate(x) int x; // x是线程变量 ``` 要使用线程变量,首先需要使用`omp_set_num_threads`设置线程,然后在并行区域中使用`omp_get_thread_num`获取当前线程的编号。下面是一个简单的示例: ```cpp #include <stdio.h> #include <omp.h> #pragma omp threadprivate(x) int main() { int x; omp_set_num_threads(4); #pragma omp parallel private(x) { x = omp_get_thread_num(); // 获取当前线程的编号 printf("Thread %d: x = %d\n", omp_get_thread_num(), x); } return 0; } ``` 在上面的例子中,我们使用了`omp_set_num_threads`将线程设为4,并在`omp parallel`指令中创建了4个并行线程。每个线程将自己的线程编号赋值给线程变量`x`,然后输出线程编号和`x`的值。 总之,OpenMP中的线程变量允许每个线程拥有自己的私有变量,从而避免了据竞争的问题,并且可以提高并行程序的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值