0. はじめに
かつて業界最強とも呼ばれた Intel C++ コンパイラがいつの間にか無償で提供されるようになっていた。正しくは Intel oneAPI と呼ばれる CPU や GPU,そして FPGA までを対象に含めた統合開発環境が無償で提供されるようになったというのだ。ただしサポートは有償である。
前回の記事では,WebP ユーティリティを評判の高い Clang を用いてビルドしてみたが,今回は業界最強と呼ばれる Intel C++ コンパイラを試してみたい。
1. Intel oneAPI ツールキットの入手
Intel 公式のページ Free Intel® Software Development Tools からダウンロードできる。このうち Intel C++ コンパイラのみを使用するのであれば Intel® oneAPI Base Toolkit のみをダウンロードすればよい。ちなみに Visual Studio 2022(もしくは 2019)を事前にインストールしておいたほうが良いだろう。
なお,この記事を書いているときのバージョンは oneAPI 2024.2, Compiler Release 2024.2.1 である。
2. コマンドライン開発環境の設定
Intel oneAPI をインストールすると,スタートメニューに
- Intel oneAPI command prompt for IA32 for Visual Studio 2022
- Intel oneAPI command prompt for Intel 64 for Visual Studio 2022
というショートカットが作られるので,ターゲットに応じて選択する。
3. コンパイラオプション
オプションの違いをまとめると以下のようになる。※赤字は32bit版のみ有効
項目 | 変数 | Visual C++ | Clang | Intel C++ |
---|---|---|---|---|
コンパイラ | CC | cl.exe | clang-cl.exe | icx-cl.exe |
コンパイラ オプション |
CCFLAGS | /O2 /GL | /O2 -flto | /O3 -flto |
ライブラリアン | LINKLIB | lib.exe | llvm-lib.exe | llvm-lib.exe |
ライブラリアン オプション |
LLFLAGS | /LTCG | ||
リンカ | LINKEXE | link.exe | lld-link.exe | lld-link.exe |
リンカ オプション |
LDFLAGS | /LTCG /SAFESEH | /SAFESEH | /SAFESEH |
ちなみにリンク時最適化オプション -flto
を用いなければ Visual C++ の lib.exe
および link.exe
を使用できる。しかし,オプション -flto
を用いると専用の llvm-lib.exe
および lld-link.exe
を使用する必要がある。Intel onAPI ツールキットに含まれる xilib.exe
や xilink.exe
でもダメなのは,それらが単に内部で lib.exe
や link.exe
を呼び出しているに過ぎないからだ。
llvm-lib.exe
および lld-link.exe
は Clang ツールのものではなく,Intel oneAPI ツールキット専用のものを使う必要があるが,名前が衝突してしまうので Intel oneAPI ツールキット専用のほうにはパスが通っていない。このため絶対パス指定で呼び出す必要がある。ちなみに llvm.exe
と lld-link.exe
が置かれているフォルダ(*)にある README.txt
には下記のコメントがある。
(*) デフォルトは C:\Program Files (x86)\Intel\oneAPI\compiler\latest\bin\compiler\
These binaries are not placed in PATH during environment setup in order to reduce collisions with other toolchains.
This is a departure from OneAPI Compiler Releases before 2022.0 (December 2021), where these tools were in PATH. There may be cases where the tools which are no longer in PATH were being invoked directly in some application Makefile (or CMake configuration) and ...
Intel oneAPI の昔のリリースではパスの中に入っていたが,他のツールチェーン(おそらく Clang のこと)との衝突を防ぐためにパスから外したとのこと。しかし,必要であれば直接呼び出しても良いようだ。
4. メイクファイル
Intel C++ コンパイラ固有部を以下に示す。最適化オプションは /O3
とした。前項で述べたようにライブラリアンとリンカは絶対パス指定で呼び出す。
#-------------------------------------------------------------------------------
# Makefile for Intel C++, release build, static link
#-------------------------------------------------------------------------------
CC = icx-cl.exe
LINKLIB = "C:\Program Files (x86)\Intel\oneAPI\compiler\latest\bin\compiler\llvm-lib.exe"
LINKEXE = "C:\Program Files (x86)\Intel\oneAPI\compiler\latest\bin\compiler\lld-link.exe"
CCFLAGS = /nologo /c /O3 /DNDEBUG /MT /I. /Isrc /W3 /EHsc
CCFLAGS = $(CCFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
CCFLAGS = $(CCFLAGS) /DHAVE_WINCODEC_H /DWEBP_USE_THREAD
CCFLAGS = $(CCFLAGS) /GS- /arch:AVX2 -flto
LLFLAGS = /nologo
LDFLAGS = /nologo /LARGEADDRESSAWARE /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE
!IF "$(VS_TARGET_ARCH)" == "x86"
LDFLAGS = $(LDFLAGS) /SAFESEH
!ENDIF
WINLIBS = ole32.lib windowscodecs.lib shlwapi.lib
!IFDEF VS_TARGET_ARCH
OUT_DIR = output\release-static\$(VS_TARGET_ARCH)intel
!ELSE
!ERROR 環境変数 VS_TARGET_ARCH が未定義です。
!ENDIF
#-------------------------------------------------------------------------------
!INCLUDE Makefile.inc
共通部は長いので以下参照されたい。
Makefile.inc(共通部)はコチラ
#-------------------------------------------------------------------------------
# このファイルは下記のメイクファイルでインクルードして使用します。
# Makefile.vc2 ... x86/x64, cl.exe
# Makefile.clang ... x86/x64, clang-cl.exe
# Makefile.intel ... x86/x64, icx-cl.exe
#-------------------------------------------------------------------------------
# 出力ディレクトリ
#-------------------------------------------------------------------------------
OUTPUT_DIRS = \
$(OUT_DIR)\lib \
$(OUT_DIR)\bin \
$(OUT_DIR)\obj\dec \
$(OUT_DIR)\obj\demux \
$(OUT_DIR)\obj\dsp \
$(OUT_DIR)\obj\enc \
$(OUT_DIR)\obj\examples \
$(OUT_DIR)\obj\extras \
$(OUT_DIR)\obj\imageio \
$(OUT_DIR)\obj\mux \
$(OUT_DIR)\obj\sharpyuv \
$(OUT_DIR)\obj\utils
#-------------------------------------------------------------------------------
# ターゲットの定義
#-------------------------------------------------------------------------------
all: \
$(OUTPUT_DIRS) \
$(OUT_DIR)\lib\libwebpdecoder.lib \
$(OUT_DIR)\lib\libsharpyuv.lib \
$(OUT_DIR)\lib\libwebp.lib \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebpmux.lib \
$(OUT_DIR)\bin\cwebp.exe \
$(OUT_DIR)\bin\dwebp.exe \
$(OUT_DIR)\bin\vwebp.exe \
$(OUT_DIR)\bin\webpmux.exe \
$(OUT_DIR)\bin\img2webp.exe \
$(OUT_DIR)\bin\get_disto.exe \
$(OUT_DIR)\bin\webp_quality.exe \
$(OUT_DIR)\bin\vwebp_sdl.exe \
$(OUT_DIR)\bin\webpinfo.exe \
$(OUT_DIR)\bin\gif2webp.exe \
$(OUT_DIR)\bin\anim_diff.exe \
$(OUT_DIR)\bin\anim_dump.exe
#-------------------------------------------------------------------------------
# オブジェクトの定義
#-------------------------------------------------------------------------------
SHARPYUV_OBJS = \
$(OUT_DIR)\obj\sharpyuv\sharpyuv.obj \
$(OUT_DIR)\obj\sharpyuv\sharpyuv_cpu.obj \
$(OUT_DIR)\obj\sharpyuv\sharpyuv_csp.obj \
$(OUT_DIR)\obj\sharpyuv\sharpyuv_dsp.obj \
$(OUT_DIR)\obj\sharpyuv\sharpyuv_gamma.obj \
$(OUT_DIR)\obj\sharpyuv\sharpyuv_neon.obj \
$(OUT_DIR)\obj\sharpyuv\sharpyuv_sse2.obj
DEC_OBJS = \
$(OUT_DIR)\obj\dec\alpha_dec.obj \
$(OUT_DIR)\obj\dec\buffer_dec.obj \
$(OUT_DIR)\obj\dec\frame_dec.obj \
$(OUT_DIR)\obj\dec\idec_dec.obj \
$(OUT_DIR)\obj\dec\io_dec.obj \
$(OUT_DIR)\obj\dec\quant_dec.obj \
$(OUT_DIR)\obj\dec\tree_dec.obj \
$(OUT_DIR)\obj\dec\vp8_dec.obj \
$(OUT_DIR)\obj\dec\vp8l_dec.obj \
$(OUT_DIR)\obj\dec\webp_dec.obj
ENC_OBJS = \
$(OUT_DIR)\obj\enc\alpha_enc.obj \
$(OUT_DIR)\obj\enc\analysis_enc.obj \
$(OUT_DIR)\obj\enc\backward_references_cost_enc.obj \
$(OUT_DIR)\obj\enc\backward_references_enc.obj \
$(OUT_DIR)\obj\enc\config_enc.obj \
$(OUT_DIR)\obj\enc\cost_enc.obj \
$(OUT_DIR)\obj\enc\filter_enc.obj \
$(OUT_DIR)\obj\enc\frame_enc.obj \
$(OUT_DIR)\obj\enc\histogram_enc.obj \
$(OUT_DIR)\obj\enc\iterator_enc.obj \
$(OUT_DIR)\obj\enc\near_lossless_enc.obj \
$(OUT_DIR)\obj\enc\picture_enc.obj \
$(OUT_DIR)\obj\enc\picture_csp_enc.obj \
$(OUT_DIR)\obj\enc\picture_psnr_enc.obj \
$(OUT_DIR)\obj\enc\picture_rescale_enc.obj \
$(OUT_DIR)\obj\enc\picture_tools_enc.obj \
$(OUT_DIR)\obj\enc\predictor_enc.obj \
$(OUT_DIR)\obj\enc\quant_enc.obj \
$(OUT_DIR)\obj\enc\syntax_enc.obj \
$(OUT_DIR)\obj\enc\token_enc.obj \
$(OUT_DIR)\obj\enc\tree_enc.obj \
$(OUT_DIR)\obj\enc\vp8l_enc.obj \
$(OUT_DIR)\obj\enc\webp_enc.obj
DSP_DEC_OBJS = \
$(OUT_DIR)\obj\dsp\alpha_processing.obj \
$(OUT_DIR)\obj\dsp\alpha_processing_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\alpha_processing_neon.obj \
$(OUT_DIR)\obj\dsp\alpha_processing_sse2.obj \
$(OUT_DIR)\obj\dsp\alpha_processing_sse41.obj \
$(OUT_DIR)\obj\dsp\cpu.obj $(OUT_DIR)\obj\dsp\dec.obj \
$(OUT_DIR)\obj\dsp\dec_clip_tables.obj \
$(OUT_DIR)\obj\dsp\dec_mips32.obj \
$(OUT_DIR)\obj\dsp\dec_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\dec_msa.obj \
$(OUT_DIR)\obj\dsp\dec_neon.obj \
$(OUT_DIR)\obj\dsp\dec_sse2.obj \
$(OUT_DIR)\obj\dsp\dec_sse41.obj \
$(OUT_DIR)\obj\dsp\filters.obj \
$(OUT_DIR)\obj\dsp\filters_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\filters_msa.obj \
$(OUT_DIR)\obj\dsp\filters_neon.obj \
$(OUT_DIR)\obj\dsp\filters_sse2.obj \
$(OUT_DIR)\obj\dsp\lossless.obj \
$(OUT_DIR)\obj\dsp\lossless_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\lossless_msa.obj \
$(OUT_DIR)\obj\dsp\lossless_neon.obj \
$(OUT_DIR)\obj\dsp\lossless_sse2.obj \
$(OUT_DIR)\obj\dsp\lossless_sse41.obj \
$(OUT_DIR)\obj\dsp\rescaler.obj \
$(OUT_DIR)\obj\dsp\rescaler_mips32.obj \
$(OUT_DIR)\obj\dsp\rescaler_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\rescaler_msa.obj \
$(OUT_DIR)\obj\dsp\rescaler_neon.obj \
$(OUT_DIR)\obj\dsp\rescaler_sse2.obj \
$(OUT_DIR)\obj\dsp\upsampling.obj \
$(OUT_DIR)\obj\dsp\upsampling_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\upsampling_msa.obj \
$(OUT_DIR)\obj\dsp\upsampling_neon.obj \
$(OUT_DIR)\obj\dsp\upsampling_sse2.obj \
$(OUT_DIR)\obj\dsp\upsampling_sse41.obj \
$(OUT_DIR)\obj\dsp\yuv.obj \
$(OUT_DIR)\obj\dsp\yuv_mips32.obj \
$(OUT_DIR)\obj\dsp\yuv_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\yuv_neon.obj \
$(OUT_DIR)\obj\dsp\yuv_sse2.obj \
$(OUT_DIR)\obj\dsp\yuv_sse41.obj
DSP_ENC_OBJS = \
$(OUT_DIR)\obj\dsp\cost.obj \
$(OUT_DIR)\obj\dsp\cost_mips32.obj \
$(OUT_DIR)\obj\dsp\cost_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\cost_neon.obj \
$(OUT_DIR)\obj\dsp\cost_sse2.obj \
$(OUT_DIR)\obj\dsp\enc.obj \
$(OUT_DIR)\obj\dsp\enc_mips32.obj \
$(OUT_DIR)\obj\dsp\enc_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\enc_msa.obj \
$(OUT_DIR)\obj\dsp\enc_neon.obj \
$(OUT_DIR)\obj\dsp\enc_sse2.obj \
$(OUT_DIR)\obj\dsp\enc_sse41.obj \
$(OUT_DIR)\obj\dsp\lossless_enc.obj \
$(OUT_DIR)\obj\dsp\lossless_enc_mips32.obj \
$(OUT_DIR)\obj\dsp\lossless_enc_mips_dsp_r2.obj \
$(OUT_DIR)\obj\dsp\lossless_enc_msa.obj \
$(OUT_DIR)\obj\dsp\lossless_enc_neon.obj \
$(OUT_DIR)\obj\dsp\lossless_enc_sse2.obj \
$(OUT_DIR)\obj\dsp\lossless_enc_sse41.obj \
$(OUT_DIR)\obj\dsp\ssim.obj \
$(OUT_DIR)\obj\dsp\ssim_sse2.obj
UTILS_DEC_OBJS = \
$(OUT_DIR)\obj\utils\bit_reader_utils.obj \
$(OUT_DIR)\obj\utils\color_cache_utils.obj \
$(OUT_DIR)\obj\utils\filters_utils.obj \
$(OUT_DIR)\obj\utils\huffman_utils.obj \
$(OUT_DIR)\obj\utils\palette.obj \
$(OUT_DIR)\obj\utils\quant_levels_dec_utils.obj \
$(OUT_DIR)\obj\utils\rescaler_utils.obj \
$(OUT_DIR)\obj\utils\random_utils.obj \
$(OUT_DIR)\obj\utils\thread_utils.obj \
$(OUT_DIR)\obj\utils\utils.obj
UTILS_ENC_OBJS = \
$(OUT_DIR)\obj\utils\bit_writer_utils.obj \
$(OUT_DIR)\obj\utils\huffman_encode_utils.obj \
$(OUT_DIR)\obj\utils\quant_levels_utils.obj
IMAGEIO_DEC_OBJS = \
$(OUT_DIR)\obj\imageio\image_dec.obj \
$(OUT_DIR)\obj\imageio\jpegdec.obj \
$(OUT_DIR)\obj\imageio\metadata.obj \
$(OUT_DIR)\obj\imageio\pngdec.obj \
$(OUT_DIR)\obj\imageio\pnmdec.obj \
$(OUT_DIR)\obj\imageio\tiffdec.obj \
$(OUT_DIR)\obj\imageio\webpdec.obj \
$(OUT_DIR)\obj\imageio\wicdec.obj
IMAGEIO_ENC_OBJS = \
$(OUT_DIR)\obj\imageio\image_enc.obj
IMAGEIO_UTIL_OBJS = \
$(OUT_DIR)\obj\imageio\imageio_util.obj
MUX_OBJS = \
$(OUT_DIR)\obj\mux\anim_encode.obj \
$(OUT_DIR)\obj\mux\muxedit.obj \
$(OUT_DIR)\obj\mux\muxinternal.obj \
$(OUT_DIR)\obj\mux\muxread.obj
DEMUX_OBJS = \
$(OUT_DIR)\obj\demux\anim_decode.obj \
$(OUT_DIR)\obj\demux\demux.obj
EXTRAS_OBJS = \
$(OUT_DIR)\obj\extras\extras.obj \
$(OUT_DIR)\obj\extras\quality_estimate.obj \
$(OUT_DIR)\obj\extras\sharpyuv_risk_table.obj
EX_UTIL_OBJS = \
$(OUT_DIR)\obj\examples\example_util.obj
EX_GIF_DEC_OBJS = \
$(OUT_DIR)\obj\examples\gifdec.obj
EX_ANIM_UTIL_OBJS = \
$(OUT_DIR)\obj\examples\anim_util.obj
#-------------------------------------------------------------------------------
# スタティックリンクライブラリ *.LIB の依存関係の定義
#-------------------------------------------------------------------------------
$(OUT_DIR)\lib\libsharpyuv.lib: $(SHARPYUV_OBJS)
$(OUT_DIR)\lib\libwebpmux.lib: $(MUX_OBJS)
$(OUT_DIR)\lib\libwebpdemux.lib: $(DEMUX_OBJS)
$(OUT_DIR)\lib\libwebpdecoder.lib: \
$(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
$(OUT_DIR)\lib\libwebp.lib: \
$(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_ENC_OBJS) \
$(ENC_OBJS) $(DSP_ENC_OBJS) $(UTILS_DEC_OBJS) \
$(OUT_DIR)\lib\libsharpyuv.lib
#-------------------------------------------------------------------------------
# 実行ファイル *.EXE の依存関係の定義
#-------------------------------------------------------------------------------
$(OUT_DIR)\bin\cwebp.exe: $(OUT_DIR)\obj\examples\cwebp.obj \
$(EX_UTIL_OBJS) \
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libsharpyuv.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\dwebp.exe: $(OUT_DIR)\obj\examples\dwebp.obj \
$(EX_UTIL_OBJS) \
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\vwebp.exe: $(OUT_DIR)\obj\examples\vwebp.obj \
$(EX_UTIL_OBJS) \
$(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\webpmux.exe: $(OUT_DIR)\obj\examples\webpmux.obj \
$(EX_UTIL_OBJS) \
$(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpmux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\img2webp.exe: $(OUT_DIR)\obj\examples\img2webp.obj \
$(EX_UTIL_OBJS) \
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libsharpyuv.lib \
$(OUT_DIR)\lib\libwebp.lib \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebpmux.lib
$(OUT_DIR)\bin\get_disto.exe: $(OUT_DIR)\obj\extras\get_disto.obj \
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\webp_quality.exe: $(OUT_DIR)\obj\extras\webp_quality.obj \
$(EXTRAS_OBJS) \
$(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\vwebp_sdl.exe: $(OUT_DIR)\obj\extras\vwebp_sdl.obj \
$(OUT_DIR)\obj\extras\webp_to_sdl.obj \
$(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\webpinfo.exe: $(OUT_DIR)\obj\examples\webpinfo.obj \
$(EX_UTIL_OBJS) \
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\gif2webp.exe: $(OUT_DIR)\obj\examples\gif2webp.obj \
$(EX_UTIL_OBJS) $(EX_GIF_DEC_OBJS) \
$(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpmux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\anim_diff.exe: $(OUT_DIR)\obj\examples\anim_diff.obj \
$(EX_UTIL_OBJS) $(EX_GIF_DEC_OBJS) $(EX_ANIM_UTIL_OBJS) \
$(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebp.lib
$(OUT_DIR)\bin\anim_dump.exe: $(OUT_DIR)\obj\examples\anim_dump.obj \
$(EX_UTIL_OBJS) $(EX_GIF_DEC_OBJS) $(EX_ANIM_UTIL_OBJS) \
$(IMAGEIO_ENC_OBJS) $(IMAGEIO_UTIL_OBJS) \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebp.lib
#-------------------------------------------------------------------------------
# 出力ディレクトリの生成
#-------------------------------------------------------------------------------
$(OUTPUT_DIRS):
@if not exist $@ mkdir $@
#-------------------------------------------------------------------------------
# ライブラリ *.LIB の生成コマンド
#-------------------------------------------------------------------------------
$(OUT_DIR)\lib\libwebpdecoder.lib \
$(OUT_DIR)\lib\libsharpyuv.lib \
$(OUT_DIR)\lib\libwebp.lib \
$(OUT_DIR)\lib\libwebpdemux.lib \
$(OUT_DIR)\lib\libwebpmux.lib:
$(LINKLIB) $(LLFLAGS) /out:$@ $**
#-------------------------------------------------------------------------------
# 実行ファイル *.EXE の生成コマンド
#-------------------------------------------------------------------------------
$(OUT_DIR)\bin\cwebp.exe \
$(OUT_DIR)\bin\dwebp.exe \
$(OUT_DIR)\bin\vwebp.exe \
$(OUT_DIR)\bin\webpmux.exe \
$(OUT_DIR)\bin\img2webp.exe \
$(OUT_DIR)\bin\get_disto.exe \
$(OUT_DIR)\bin\webp_quality.exe \
$(OUT_DIR)\bin\vwebp_sdl.exe \
$(OUT_DIR)\bin\webpinfo.exe \
$(OUT_DIR)\bin\gif2webp.exe \
$(OUT_DIR)\bin\anim_diff.exe \
$(OUT_DIR)\bin\anim_dump.exe:
$(LINKEXE) $(LDFLAGS) /out:$@ $** $(WINLIBS)
#-------------------------------------------------------------------------------
# オブジェクト *.OBJ の生成コマンド
#-------------------------------------------------------------------------------
{examples}.c{$(OUT_DIR)\obj\examples}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\examples\ $<
{extras}.c{$(OUT_DIR)\obj\extras}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\extras\ $<
{imageio}.c{$(OUT_DIR)\obj\imageio}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\imageio\ $<
{sharpyuv}.c{$(OUT_DIR)\obj\sharpyuv}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\sharpyuv\ $<
{src\dec}.c{$(OUT_DIR)\obj\dec}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\dec\ $<
{src\dsp}.c{$(OUT_DIR)\obj\dsp}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\dsp\ $<
{src\enc}.c{$(OUT_DIR)\obj\enc}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\enc\ $<
{src\mux}.c{$(OUT_DIR)\obj\mux}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\mux\ $<
{src\demux}.c{$(OUT_DIR)\obj\demux}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\demux\ $<
{src\utils}.c{$(OUT_DIR)\obj\utils}.obj::
$(CC) $(CCFLAGS) /Fo$(OUT_DIR)\obj\utils\ $<
#-------------------------------------------------------------------------------
# 生成物のクリーンナップ
#-------------------------------------------------------------------------------
clean:
@if exist $(OUT_DIR) rd /s /q $(OUT_DIR)
メイクファイルの実行は 32bit or 64bit いずれかの開発環境で下記のコマンドを実行するだけだ。
nmake -f Makefile.intel
生成物は下記のフォルダに作られる。
コンバイラ | ターゲット | フォルダ |
---|---|---|
Visual C++ | 32bit | output\release-static\x86vc\bin |
64bit | output\release-static\x64vc\bin |
|
Clang | 32bit | output\release-static\x86clang\bin |
64bit | output\release-static\x64clang\bin |
|
Intel C++ | 32bit | output\release-static\x86intel\bin |
64bit | output\release-static\x64intel\bin |
5. バイナリサイズの比較
original とはWebP のダウンロードリポジトリからダウンロードしたものである。
コンパイラ | 32bit版 | 64bit版 |
---|---|---|
original | なし | 742,912 bytes |
Visual C++ | 609,280 bytes | 749,056 bytes |
Clang | 817,152 bytes | 866,816 bytes |
Intel C++ | 814,592 bytes | 866,816 bytes |
6. パフォーマンス比較
題材は前々回の記事で用いたサンプル画像である。300dpiでスキャンしたカラー画像4枚,白黒画像36枚のビットマップファイル *.BMP を cwebp.exe
を用いて可逆圧縮(lossless)モードかつ最高品質 z=9
にて圧縮した際に要した計算時間の平均値を示す。original を基準100とした相対値で示す。
なお,今回もインテル第8,11,13世代のプロセッサで比較した。
ちなみに第8世代を 100 とすると,第11世代は 70~75,第13世代は 50~55 となる。
7. まとめ
-
やはり Intel C++ コンパイラは最強である。
-
ただし,プロセッサの世代が新しくなるにつれて Intel C++ コンパイラの優位性が徐々に小さくなっていくのが悲しいところである。
-
最大の課題は Intel C++ コンパイラは機能・オプションが多過ぎて*正直*使いこなすのが難しいことだろうか。