PerlMagick が OpenMP 有効だと高負荷になる件

ImageMagick と PerlMagick を使った CGI が原因不明の高負荷になり、ドツボに嵌ったので、備忘録として残しておくことにします。結論からすると apache + ImageMagick + PerlMagick を安定稼働させるには ImageMagick を OpenMP 無効化してコンパイルする必要があるようです。

具体的には下記のようなオプションを付けてコンパイルを行うことで安定動作となります。
※ --disable-openmp --disable-opencl は一緒に指定する必要があります。

cd /usr/local/src/
wget http://image_magick.veidrodis.com/image_magick/ImageMagick-6.7.4-2.tar.gz
tar xvfz ImageMagick-6.7.4-2.tar.gz
cd ImageMagick-6.7.4-2
./configure --disable-openmp --disable-opencl --enable-shared --with-perl
make
make install

以下検証結果まとめです。

- スポンサーリンク -

PerlMagick を使った簡単な検証コード

下記のように二枚の画像を構成する簡単なプログラムを検証コードとします。

 +  = 

#!/usr/bin/perl
use Image::Magick;

my $img = Image::Magick->new;  $img->Read("blankface.gif");
my $img2= Image::Magick->new;  $img2->Read("kao.png");

$img->Composite( image => $img2, compose => 'over', x => 0, y => 0 );
my $output = 'composite.png';
$img->Write($output);

print "Content-type: image/png\n\n";
open my $fh, '<', $output;
binmode $fh;
print <$fh>;
close $fh;


OpenMP 有効/無効 ImageMagick での apache bench 結果

それぞれ下記のような configure オプションで ImageMagick をコンパイルします。with-perl オプションで PerlMagick も同時にインストールします。

OpenMP 有効

./configure --enable-shared --with-perl && make && make install

OpenMP無効

./configure --disable-openmp --disable-opencl --enable-shared --with-perl && make && make install

configure の出力確認で OpenMP の有効/無効が確認できます。無効時には赤文字は NULL です。

Options used to compile and link:
  PREFIX          = /usr/local
  EXEC-PREFIX     = /usr/local
  VERSION         = 6.7.4
  CC              = gcc -std=gnu99 -std=gnu99
  CFLAGS          = -fopenmp -g -O2 -Wall -pthread
  CPPFLAGS        = -I/usr/local/include/ImageMagick
  PCFLAGS         = -fopenmp
  DEFS            = -DHAVE_CONFIG_H
  LDFLAGS         = -L/usr/lib
  MAGICK_LDFLAGS  = -L/usr/local/lib -L/usr/lib
  LIBS            = -lMagickCore -llcms -ltiff -lfreetype -ljpeg -lpng12 -lfontconfig -lXext -lXt -lSM -lICE -lX11 -lbz2 -lxml2 -lz -lm -lgomp -lpthread 
  CXX             = g++
  CXXFLAGS        = -g -O2 -pthread
  FEATURES        = OpenMP 


apache bench による性能比較を行います。OpenMP 有効版で試験、OpenMP 無効版で試験した結果を見やすく編集してしています。同時接続数を 10、リクエスト数を 1000 で試験してみました。

ab -n 1000 -c 10 'http://localhost/test/test.cgi'

実行結果比較です。OpenMP 無効化の場合の方が 7.5 倍の性能であることが確認できました。

OpenMP無効化
Concurrency Level:      10
Time taken for tests:   27.19970 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1383442 bytes
HTML transferred:       1265000 bytes
Requests per second:    37.01 [#/sec] (mean)
Time per request:       270.200 [ms] (mean)
Time per request:       27.020 [ms]
Transfer rate:          50.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   8.3      0     142
Processing:    29  268 504.0    146    7907
Waiting:        0  253 480.1    133    7905
Total:         29  268 504.2    147    7907
OpenMP有効化
Concurrency Level:      10
Time taken for tests:   205.12334 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1381132 bytes
HTML transferred:       1265000 bytes
Requests per second:    4.88 [#/sec] (mean)
Time per request:       2050.123 [ms] (mean)
Time per request:       205.012 [ms]
Transfer rate:          6.58 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3  40.3      0     689
Processing:    35 2046 1589.5   1553   11708
Waiting:       34 1100 1155.6    734    9594
Total:         35 2049 1592.1   1555   11708

top コマンドによる負荷確認と比較です。OpenMP 無効時の方が CPU 使用率もロードアベレージも低いことが確認できます。

OpenMP無効化

top - 07:40:55 up 9 days, 22:41,  3 users,  load average: 5.09, 1.20, 0.43
Tasks:  88 total,  11 running,  77 sleeping,   0 stopped,   0 zombie
top - 07:44:16 up 9 days, 22:44,  3 users,  load average: 5.08, 1.75, 0.71
Tasks:  88 total,  19 running,  68 sleeping,   0 stopped,   1 zombie
Cpu(s): 80.2%us, 19.5%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.3%si,  0.0%st
Mem:    510540k total,   354216k used,   156324k free,    25500k buffers
Swap:  2048276k total,    15536k used,  2032740k free,   235096k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
14953 apache    17   0 77600 6032 3004 R  2.0  1.2   0:00.06 test.cgi          
14915 apache    18   0     0    0    0 R  1.3  0.0   0:00.04 test.cgi          
14948 apache    17   0 76640 5108 3000 R  1.3  1.0   0:00.04 test.cgi          
14959 apache    17   0 76772 5220 3000 R  1.3  1.0   0:00.04 test.cgi          
14960 apache    15   0     0    0    0 Z  1.3  0.0   0:00.04 test.cgi          
13947 root      15   0 12724 1056  808 R  0.7  0.2   0:00.11 top               
14160 root      15   0 63272 2824 2104 S  0.7  0.6   0:00.15 ab                
14887 apache    18   0 23292 2204 1356 R  0.7  0.4   0:00.02 test.cgi          
20701 apache    15   0  183m 4216 1240 S  0.7  0.8   0:00.12 httpd             
20728 apache    15   0  183m 4216 1240 S  0.7  0.8   0:00.17 httpd             
14956 apache    18   0 23292 2224 1356 R  0.3  0.4   0:00.01 test.cgi          
14958 apache    17   0 76640 5144 3000 R  0.3  1.0   0:00.01 test.cgi          
14961 apache    15   0 76304 3016 1812 R  0.3  0.6   0:00.01 test.cgi          
20636 apache    15   0  183m 4216 1240 S  0.3  0.8   0:00.12 httpd             
20637 apache    15   0  183m 4216 1240 S  0.3  0.8   0:00.14 httpd             
20639 apache    15   0  183m 4224 1248 S  0.3  0.8   0:00.16 httpd             
20642 apache    15   0  183m 4216 1240 S  0.3  0.8   0:00.16 httpd             

OpenMP有効化

top - 07:50:56 up 9 days, 22:51,  3 users,  load average: 13.86, 7.02, 3.02
Tasks:  86 total,   6 running,  75 sleeping,   0 stopped,   5 zombie
Cpu(s): 97.7%us,  2.2%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.2%si,  0.0%st
Mem:    510540k total,   399148k used,   111392k free,    27868k buffers
Swap:  2048276k total,    15536k used,  2032740k free,   263652k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
18462 apache    18   0 88376 7624 3936 R 16.0  1.5   0:00.48 test.cgi          
18459 apache    17   0     0    0    0 Z 15.0  0.0   0:00.45 test.cgi 
18446 apache    18   0     0    0    0 Z 10.7  0.0   0:00.32 test.cgi 
18450 apache    18   0     0    0    0 Z 10.0  0.0   0:00.30 test.cgi 
18452 apache    18   0     0    0    0 Z 10.0  0.0   0:00.30 test.cgi 
18455 apache    18   0 88380 7628 3932 S  9.7  1.5   0:00.29 test.cgi          
18444 apache    18   0 88376 7624 3932 S  8.7  1.5   0:00.26 test.cgi          
18399 apache    19   0 88520 7832 4024 R  6.7  1.5   0:00.54 test.cgi          
18458 apache    18   0 88376 7480 3904 S  4.3  1.5   0:00.13 test.cgi          
18401 apache    19   0     0    0    0 Z  3.7  0.0   0:00.35 test.cgi 
16822 root      15   0 63272 2824 2104 R  0.3  0.6   0:00.17 ab                
20643 apache    15   0  183m 4216 1240 S  0.3  0.8   0:00.21 httpd             
20703 apache    15   0  183m 4216 1240 S  0.3  0.8   0:00.23 httpd             
    1 root      15   0 10352  444  408 S  0.0  0.1   0:04.57 init              
    2 root      RT  -5     0    0    0 S  0.0  0.0   0:12.33 migration/0       
    3 root      34  19     0    0    0 S  0.0  0.0   0:00.07 ksoftirqd/0       
    4 root      RT  -5     0    0    0 S  0.0  0.0   0:00.03 watchdog/0        

上記のような理由で、ImageMagick をソースから単に ./configure && make && make install
でインストールした場合に、PerlMagick を使った CGI を動かすとサーバが高負荷状態になる可能性があります。プログラムとしては問題がないので、一見原因不明の高負荷と見えてしまうのですが、実は ImageMagick のコンパイルオプションでしたって話です。

ちなみに、yum でインストールした場合には、上記のような問題は発生しませんでした。インストールされたバージョンは 6.2.8 でしたが、openmp が無効化(or 6.2.8 はopenmp 未サポート)されていたため安定稼働していました。

yum -y install ImageMagick*

openmp が有効化されているかは convert -version で確認可能です。以下実行結果です。

$ convert -version
Version: ImageMagick 6.7.4-2 2011-12-27 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
Features: OpenMP    

$ convert -version
Version: ImageMagick 6.7.4-2 2011-12-27 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
Features:     

$ /usr/bin/convert -version
Version: ImageMagick 6.2.8 10/20/10 Q16 file:/usr/share/ImageMagick-6.2.8/doc/index.html
Copyright: Copyright (C) 1999-2006 ImageMagick Studio LLC

参考情報
ImageMagickとマルチスレッドは混ぜるなキケン!? - shimada-kの日記:
組み込みマルチコア進化論(5):マルチコアにおける標準表記OpenMP (1/3) - @IT MONOist:

- スポンサーリンク -