1. 程式人生 > >GraphicsMagick在多執行緒環境工作時其自身多執行緒處理會變成單執行緒

GraphicsMagick在多執行緒環境工作時其自身多執行緒處理會變成單執行緒

修改編譯引數進行測試

./configure --enable-openmp-slow --enable-shared

改為動態載入庫後容易出現的問題:

sudo mv /usr/local/lib/libpng12.so.0 /usr/local/lib/libpng12.so.0.bak

sudo ln -s /usr/lib64/libpng12.so.0 /usr/local/lib/libpng12.so.0

修改GM使用的執行緒數的設定:

export OMP_NUM_THREADS=8

OMP_NUM_THREADS數

實時生成執行緒數

cpu佔用

load_mem時間

default

12

225.3%

50ms

default

24

215.2%

112ms

default

36

227.0%

164ms

伺服器配置:16核
名詞:
GM的C core: C language API for the lowest-level core programming interface 
GM的C++API: Magick++ provides an abstract object-oriented C++ interface. 
使用兩套API測試的原因是因為GM本身自帶的程式gm是使用C core的api,其執行時候的CPU利用率和處理速度與現在C++API有所不同。


壓力測試分為GM自帶命令列多執行緒測試和使用GM的api多執行緒測試以及不同版本的GM測試。
自帶命令列多執行緒測試命令:
gm benchmark -iterations 1000 -stepthreads 1 convert -resize 100x100 -quality 90 +profile "*" ./test.jpg ./100x100.jpg
結果:執行緒數自增一,預設最多執行緒使用為系統核數,最多執行緒使用可通過環境變數OMP_NUM_THREADS進行設定。並且隨著執行緒數的增 加 CPU的利用率在提升,最高可到1500%多。


單程序中使用GM庫中C++API處理圖片與使用GM庫的C core的API處理圖片測試:
結果:C++API處理圖片不能發揮GM庫OpenMP的多執行緒的效果,CPU使用最多達到100%。使用自動C core處理圖片可以發揮GM自身多執行緒處理圖片的效果,CPU使用情況隨著執行緒數的增加而增加。

多執行緒中使用GM庫中C++API處理圖片與使用GM庫中C core的API處理圖片測試:
結果:GM 的C++API處理圖片依舊是單執行緒執行,OpenMP的設定不起作用,CPU利用率最多200%。使用GM的C core的API在多執行緒環境中OpenMp多執行緒處理圖片失效表現為單執行緒的情況,CPU利用率最多200%。

實時生成測試:
結果:隨著實時生成中執行緒數的設定變大loadmem的時間在有壓力的情況會增加。
壓力測試用例:
./ab -n100000 -c200 -k

http://192.168.128.15/pic/r/00/a0/fc6a3bd10b3016c4000e49c2ac5f_400_300.c1.jpeg >> test_result/gm1.log
./ab -n100000 -c200 -khttp://192.168.128.15/pic/r/79/ab/a280d338458393fff446ff5088ab_247_310.c1.jpg >> test_result/gm2.log

隨後改變OMP_NUM_THREADS的數目對以上測試結果沒有影響,也就是說GM自身多執行緒處理圖片在多執行緒環境中其實是無效的。

使用多程序測試:
使用的GM的C core API,在多程序環境下處理圖片CPU利用率可以根據環境變數OMP_NUM_THREADS的數目進行設定。OMP_NUM_THREADS是 OpenMP的執行緒數。
該執行緒數決定了GM處理圖片時候使用的執行緒。

GM的版本共測試了兩個分別為1.3.17和1.3.18,兩個版本表現的效果是一樣的。



最終結論:GM圖片處理庫在單程序環境中處理圖片而且使用自身C core的API時才能發揮其“瑞士軍刀”的效果,在多執行緒環境中OpenMp會失效,GM表現的是單執行緒處理圖片。

因此想要提升GM多執行緒處理的速度的話宿主程式是多執行緒的情況是不行的。由於GM自身的侷限以後的優化空間可以是多程序處理圖片。

有關該問題作者的回覆:

On Wed, 8 May 2013, 王利超 wrote:

> hi,all:
>         I find GraphicsMagick doesn't work well if the program self is multi thread。The CPU is only 200%  (my
> computer is 16 core).
>        The C++ API of GraphicsMagick is not working when  users program  is  multi thread,openMP
> in GraphicsMagick  is not like  paralle process.

> My test GraphicsMagick versions are :1.3.18 ,1.3.17 ,1.3.16
> single threads test case is like:

The problem is almost certainly because the JPEG coder has been marked 
as not thread safe.  Take a look at RegisterJPEGImage() in 
magick/jpeg.c.

You could experiment by commenting out the two lines that say

   entry->thread_support=False; /* libjpeg is not thread safe */

or change from False to True.

or you could try this non-recommended approach (casts away const) with 
existing binaries:

    MagickInfo *magick_info=("JPEG",MagickInfo &exception);
    magick_info->thread_support=MagickTrue;
    MagickInfo *magick_info=("JPG",MagickInfo &exception);
    magick_info->thread_support=MagickTrue;

before reading/writing the JPEG files.  Please let us know how it 
turns out.  The JP2, PNG, and TIFF coders are marked the same way.

As far as I am aware, only the JPEG error reporting might not be 
thread safe because it uses setjmp()/longjmp() and behavior of these 
functions in multi-threaded programs is not well-defined because some 
processor context might not be restored, or the processor context 
restored might not be correct (for example, the longjmp() might occur 
on a different CPU than the original setjmp()).  This is highly OS and 
CPU dependent.

I do have an idea for how to eliminate use of setjmp()/longjmp() but 
it would then depend on POSIX threads features.

Bob
-- 
Bob Friesenhahn
[email protected], http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer,    http://www.GraphicsMagick.org/