Omni Graffleなどで作った影の付いた図を、TeXでincludeしたい時がありますよね。 この時、dvipdfmxコマンドを用いてDVI -> PDFの変換をすると、非常に時間がかかることがあります。 図のサイズ等をいじれば多少は処理時間が少なくなりますが、図が汚くなってしまうなんてことも。。。 図の方は変化させずに速く処理を終える方法はないのでしょうか?
dvipdfmxを動かしている時にCPU使用率を見てみましょう。 どうやらdvipdfmxは1コアしか使っていないみたいですね。 ということは、複数のコアで処理を行えば速くできそうです。 (え?1コアしかないCPUを使っている? うーん、残念ながらそういう人にはこのページの内容は役に立たないかも。。。)
ということで、複数のコアに並列にdvipdfmxの処理をさせるシェルスクリプトdvipdfmxpを 作ってみました。 (最後の"p"はparallelから来ています。)
ちなみに、豊岡の使っている環境(Intel Core 2 Quad Q6600 2.4GHz)では、従来58秒かかっていた 論文のPDF変換処理が、16秒で行えるようになりました!
現在、Linuxで動作確認を行ったバージョンのみがあります。
dvipdfmxpをダウンロードdvipdfmxpは内部でdvipdfmxとpdftkを用います。 Debian系のLinuxだと、以下のようにしてインストールできます。
# apt-get install dvipdfmx pdftk
dvipdfmxpの簡単な使い方は以下のようになります。
% dvipdfmxp dvifile num_page [num_process]
dvipdfmxには変換するページを指定するオプション "-s" があります。 これを使えばDVI -> PDFの変換が1ページずつできますね。 この処理は並列に実行できるので、xargsコマンドを使って並列実行してしまうことが可能です。
しかし、1ページずつPDFに変換すると、1ページのPDFファイルが大量にできることになります。 これはpdftkコマンドを使って1つのPDFファイルに結合することができます。
以下が作成したスクリプトになります。
#!/bin/sh
# dvipdfmxp - Parallel dvipdfmx
# Written by Hiraku Toyooka, 2010.
# default max_procs given to xargs
num_process=4
usage()
{
echo Usage: dvipdfmxp dvifile num_page [num_process]
}
do_dvipdfmxp()
{
dvifile=$1
name=`echo $dvifile | sed -e s/\.dvi//`
num_page=$2
args=""
pdfs=""
i=1
while [ $i -le $num_page ]; do
args="${args}-q -o ${i}.pdf -s ${i} ${dvifile} "
pdfs="${pdfs}${i}.pdf "
i=`expr $i + 1`
done
echo "$args" | xargs -P${num_process} -n6 dvipdfmx
pdftk $pdfs cat output ${name}.pdf
rm [0-9]*.pdf
}
main()
{
ls [0-9]*.pdf 2>/dev/null 1>/dev/null
status=`echo $?`
if test $status -eq 0; then
echo "[0-9]*.pdf already exist. Please delete or move these files."
exit 1
fi
if test $# -eq 2; then
do_dvipdfmxp $*
elif test $# -eq 3; then
num_process=$3
do_dvipdfmxp $*
else
usage
fi
}
main $*
dvipdfmxpにはまだまだいたらない所があるかと思います(特にページ数を指定しないといけない所とか)。 改善していくためのコメントやバグ報告などをいただけると非常に助かります。
コメント等の宛先: hiraku (at) softlab.cs.tsukuba.ac.jp