Faiss使用多线程出现的性能问题

faiss在增加CPU的情况下,反而出现效率低下的问题。

从理论上看,作为一个CPU/GPU计算型的应用,更多的核意味着更大的计算吞吐能力,性能只会越来越好才是。

在实际过程中,通过taskset命令分配更多的核给faiss只会带来更长响应时间以及更大的响应时间偏差(variation)。

faiss的主要流程:建库(train)、校验(sanity check)、搜索。

由于建库是一次性操作,就不考虑建库带来的影响。对校验分析,也没有发现需要耗时太多的时间,那么主要问题就在搜索上面。

对于”核心越多,性能越差”的奇怪表现,搜索阶段又分两个部分,一个是quantizer,一个是search_preassigned。考虑应该跟线程的计算有关,于是将nprobe值和batch设置强置为1,从算法上保证search_preassigned只能用单核单线程。结果发现多核cpu依然满载。

那么直接用perf top命令查看系统调用栈。发现在多核、单线程的模式下占比最高的居然是libgomp,而真正的benchmark(6-IVFPQ)只占了很少的CPU资源。

这就是核心的问题了:

  1. Faiss的多核心是通过openMP实现的。
  2. 默认OMP_NUM_THREADS等于所有可用的CPU数,即OpenMP默认将会在启动与核心数相同的线程数作为线程池。
  3. 默认情况下,openmp假定所有的调用都是计算密集型的。为了减少线程启动/唤醒过程需要上下文开销,系统必须时刻保证每一个线程都是alive状态。换句话说,要让线程活着,OpenMP会让线程池的每个线程做大量的无意义计算占据时间片而不是wait挂起。
  4. quantizer 的过程中系统启动了omp线程池,理论上在修改后的search_preassigned开始后,线程池已经没有任何意义。但在放任不管的情况下,系统的每个核心的CPU使用率都会被空白计算占据,理论上100%。主线程结束之前线程池不会自己销毁。
  5. 这个时候如果位于主线程上的search_preassigned函数需要执行,那就不得不与OMP线程池抢占CPU time。这就是核心越多性能越差的原因。而放大这个影响的原因是我们的测试程序经过了变态级别的优化之后导致OMP的线程维护开销远远大于任务的CPU开销(微秒级响应,少于0.1个最小上下文)。这个测试事实上成为了某种程度“系统调度时延”测量。这个结果恰恰反应了预期。

剩下的就是解这个问题了,那只要在合适的时候让线程池销毁所有线程就迎刃而解了。OpenMP的实现是基于编译器的,发现没有办法可以直接实现目的,只有两个对应的环境变量可以缓解:

  • GOMP_SPINCOUNT= omp线程经过了n个spin lock之后便被挂起。自然,n值越小就越早的挂起线程。
  • OMP_WAIT_POLICY=PASSIVE 通过使用wait方法挂起 omp线程。对应的ACTIVE 意味着线程池中的线程始终处于活动状态——消耗大量的CPU。

看上去效果还是不错的。

PS:并没有对所有情况进行测试,现在的结果指向是由于faiss依赖的openblat库中额外的omp线程池出现了问题导致主线程性能受到影响。理论上多线程也会如此,只是概率上导致看上去性能不是线性下降。

然后OMP_WAIT_POLICY的问题,主要是对在openmp下使用OpenBLAS的BLAS实现的时候起作用,此外,如果用了MKL库,一定条件下的MKL同样也会触发。

然后在faiss建立索引(train),也可能会出现这种情况,使用最新的faiss1.6.5及以后建立索引,CPU占用率明显有下降。

参考:http://www.litrin.net/2020/03/26/faiss的多线程效率问题/

https://www.cnblogs.com/yhzhou/p/10568728.html

https://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html

Faiss使用多线程出现的性能问题的更多相关文章

  1. [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)

    [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...

  2. [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)

    [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...

  3. [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)

    [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...

  4. DirectX* 11 多线程渲染的性能、方法和实践

    对于在 CPU 上运行的 PC 游戏,渲染通常是主要的性能瓶颈:多线程渲染是一种消除瓶颈的有效方法.本文研究了 DirectX* 11 多线程渲染的性能可扩展性,讨论了多线程渲染的两种基本方法,并介绍 ...

  5. DELPHI用const来提高应用程序在多核多线程下的性能

    来自:http://bbs.csdn.net/topics/330048800 --------------------------------------------------------- 我们 ...

  6. 【原创】python多线程测试接口性能

    除了使用性能测试工具进行性能测试,我们也可以直接用python多线程进行性能测试. 下面,使用这几个模块,对一个查询接口做性能测试: requests:发送http请求 json:返回的字符串转换成j ...

  7. 【Bugly干货】Android性能优化典范之多线程篇

    本文涉及的内容有:多线程并发的性能问题,介绍了 AsyncTask,HandlerThread,IntentService 与 ThreadPool 分别适合的使用场景以及各自的使用注意事项,这是一篇 ...

  8. [转载] Python的GIL是什么鬼,多线程性能究竟如何

    原文: http://cenalulu.github.io/python/gil-in-python/ GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器( ...

  9. python GIL 全局锁,多核cpu下的多线程性能究竟如何?

    python GIL 全局锁,多核cpu下的多线程性能究竟如何?GIL全称Global Interpreter Lock GIL是什么? 首先需要明确的一点是GIL并不是Python的特性,它是在实现 ...

随机推荐

  1. Leetcode春季活动打卡第三天:面试题 10.01. 合并排序的数组

    Leetcode春季活动打卡第三天:面试题 10.01. 合并排序的数组 Leetcode春季活动打卡第三天:面试题 10.01. 合并排序的数组 思路 这道题,两个数组原本就有序.于是我们采用双指针 ...

  2. Kafka之--自动启动zookeeper & kafka 脚本

    1) 首先配置SSH免密登录,在这里我用kafka(151)这台机器来作为启动脚本的存放和执行机器 [root@kafaka3 .ssh]# pwd #生成SSH KEY /root/.ssh [ro ...

  3. WEB安全新玩法 [9] 重置密码之验证流程防绕过

    一般来说,业务流程中出现多个操作环节时,是需要顺序完成的.程序设计者往往按照正常用户的操作顺序实现功能,而忽略了攻击者能够绕过中途环节,直接在后续环节上进行非法操作.iFlow 业务安全加固平台能够在 ...

  4. 使用Pycharm创建Django项目无法创建app.

    Python3.7使用Django1.11.7创建Django项目报以下错误时: 在使用Pycharm创建Django项目报以下错误时: Traceback (most recent call las ...

  5. 第九篇 -- 可以上网,连WIFI弹出网页

    最近在调试WIFI模块时,程序路径没走对,导致运行了其他的函数,修改了配置文件,之后每次连接WIFI时都会弹出网页,并且明明可以上网,下面电脑符号那儿还会出现黄标,甚是心烦.上网搜索一番,终是解决了. ...

  6. 利用C++11可变模板,封装调用dll导出函数

    起因 开发中经常需要动态调用一些导出函数,试着利用C++11特性封装一下 尝试 常规使用 typedef int WINAPI (*TMessageBoxA)(HWND hWnd,LPCSTR lpT ...

  7. 深入刨析tomcat 之---第4篇 tomcat4.0连接池 实现原理

    writedby 张艳涛

  8. Django JSONField/HStoreField SQL注入漏洞(CVE-2019-14234)

    复现 访问http://192.168.49.2:8000/admin 输入用户名admin ,密码a123123123 然后构造URL进行查询,payload: http://192.168.49. ...

  9. 【GCC编译器】Swing Modulo Scheduling

    1. SMS 在 GCC 中的实现 1.1. 一些基本概念 (1)软流水(Software pipelining )是一种通过重叠不同迭代的指令,使其并行执行,从而改进循环中指令调度的技术.关键思想是 ...

  10. Python正则表达式re库的初次使用入门

    正则表达式常用操作符: 操作符 说明 实例 . 表示任何单个字符,不包括换行符 [] 字符集,对单个字符给出取值范围 [abc]表示a.b.c,[a-z]表示a到z单个字符 [^ ] 非字符集 [^a ...