VS2010环境与OpenMP远程多线程访问MySQL数据库的限制和困惑

      标准C++代码,打开OpenMP编译选项得到debug/release版本的可执行程序A.exe,A.exe是一个socket监听服务,监听端口port的请求。A接收到请求会创建一个新的线程t去调用B.dll中的算法完成计算任务,并返回线程t的执行时间。B.dll中会有查询MySQL数据的操作,查询分为2种类型:批量查询和单个查询。线程t会执行部分OpenMP代码,OpenMP for循环代码部分包含了向mysql数据库查询单个数据的语句。批量查询得到的数据放在内存中,因此可以被线程t所启动的多个OpenMP线程(我是4核8线程的i7CPU,一般我设置启动8个OpenMP线程,正常情况下CPU利用率能到90%以上)所共享,访问这部分数据不需要加锁。但是OpenMP for循环代码部分的数据库连接代码必须加锁,否则会有访问冲突。实际上线程t所启动的若干个新的线程是共享的同一个mysql数据库连接,但是mysql本身并不支持多线程共享同一个数据库连接且进行同时的数据库请求。所以在OpenMP内部进行数据库查询时我都加上了锁。

      但是即便如此,我依旧遇到了相当奇怪的问题,描述如下:

(1)在pc1执行A.exe进行服务监听,在pc1上执行C.exe向A.exe发送socket数据包,请求访问查询位于pc2上的数据库:

        现象:在编译A.exe程序的VS2010环境中按F5启动A.exe的debug或者release版本,均可达到并行效果。在Windows资源管理器中找到A.exe的debug/release版本程序,双击执行(脱离VS2010程序),再次发送相同的socket请求到A.exe,结果发现程序为串行效果执行,CPU利用率不足10%,但是OpenMP确实已经按要求创建了新的线程,只不过看起来所有的线程都像是拥挤在同一个CPU核心上执行。

(2)在pc1执行A.exe进行服务监听,在pc1上执行C.exe向A.exe发送socket数据包,请求访问查询位于pc1上的数据库:

        现象:在编译A.exe程序的VS2010环境中按F5启动A.exe的debug或者release版本,均可达到并行效果。在Windows资源管理器中找到A.exe的debug/release版本程序,双击执行(脱离VS2010程序),再次发送相同的socket请求到A.exe,结果发现程序也可达到并行执行效果。

(3)在pc2上执行A.exe、C.exe,访问位于pc1上的数据库时,效果同(1),访问位于pc2上的数据库时,效果同(2)。这说明(1)(2)2个现象具有一定的普遍性。pc1和pc2同为i7 4核心8线程CPU,但是具体型号和主频不同,mysql数据库一致,且处于同一局域网网段内,无防火墙。

困惑:

         1、mysql不支持多线程共享1个数据库连接并发访问数据库,我在openmp for循环内已经给执行数据库访问的部分加锁,但为何不管是在VS2010环境中启动程序还是在外部执行程序,访问本机数据库时依旧能得到高度的并行执行效果呢?

         2、若上面一条的原因是mysql查询的效率极高,各个线程独占数据库连接进行查询的时间开销可以忽略不计所导致,这样就可以解释得到的高度并行化执行结果的现象,但是又有疑问:那为何脱离了VS2010环境执行OpenMP程序访问非本机数据库时相同的代码不仅不能得到相同的并行效率,反而效果类似根本没开OpenMP?(实际上我们已经监测到OpenMP启动了所要求的线程,只是各个线程表现出来的执行效率类似于运行在一个CPU核心上)。

        因此,在VS2010环境中,通过OpenMP多线程方式,不管是访问本地还是非本地mysql数据库,都可以达到高度的并行效果。但是一旦脱离了VS2010环境再去执行OpenMP程序,只有在访问本地数据库时才能得到高度的并行执行效果,访问非本地mysql数据库只能得到类似串行程序的执行效果,但是OpenMP已经按要求启动了多个线程,谁能告诉我为什么?

附MySQL多线程客户端访问数据库的说明和注意事项(我还没大看明白):http://dev.mysql.com/doc/refman/5.0/en/threaded-clients.html

补充一点:可能上面程序调用比较啰嗦,我又重新做了个实验,单独的A.exe(依赖于B.dll,这个动态库会去开启OpenMP并且访问mysql,省去了C.exe)执行,依然是同样的现象,结果没有变化。

原文地址:https://www.cnblogs.com/yeahgis/p/2622340.html