ページ更新: 2015-09-04 (金) (2760日前)
関連: C++, ソフト/CUDA, ソフト/OpenCV, Windows/VisualStudio, Intel Threding Building Blocks?, Microsoft Parallel Pattern Library?, Microsoft C+AMP? (2010-10-20) C/C++/Fortran コンパイラ用の並列処理環境「OpenMP」の情報源とメモ。 目次 OpenMP とは #(2012-09-24) OpenMP は、C/C++, FORTRAN用の並行処理環境の規格の1つ。 この規格は非営利団体 OpenMP Architecture Review Board によって管理されている。 コンパイラ・ディレクティブ (C/C++の場合 #pragma omp) を用いて、並列化の指示を行う。 OpenMP なし/あり の双方で動作するプログラムを比較的容易に記述することが出来る。 [編集]OpenMP の特徴 #(2012-09-24)
OpenMP に向いているコード #(2012-09-24)
情報源 #[編集]ニュース #
OpenMP.org #
OpenMP 4.0:
cOMPunity - The Community of OpenMP Users #[編集]iSUS #
Intel (インテルコンパイラー), XLSoft #(2011-02-02) インテルコンパイラー向けの資料だが、コンパイラーに依存する内容はほとんど書かれていない。 よって、OpenMP の入門資料として役立つ。
Intel Parallel Studio #OpenMP と Intel TBB に対応した開発統合環境。Windows では Visual Studioに統合して用いる。Intelの製品。評価版あり。
Microsoft (Visual Studio, Windows SDK) #(2011-02-02) Visual Studio 2005 で OpenMP 2.0 (March 2002) に対応した。プリプロセッサシンボル _OPENMP の値は 200203。
GCC #(2014-04-25, 2011-02-02) gcc 4.2 で OpenMPに正式に対応している。(gcc 4.1で一部対応?) gcc 4.9 で OpenMP 4.0に対応。 コンパイルオプションは「-fopenmp」を用いる。
GNU libc++ Parallel Mode #(2012-09-17, 2012-09-19) Parallel Mode とは、GNU C++ Library (GNU libstdc++) に含まれる STL の一部 (algorithm) の OpenMP 対応版である。 現時点では <algorithm> と <numeric> の関数の一部に OpenMP 適用版が用意されている。 Paralell Mode の関数を用いるには、次の2つの方法がある。
なお、手元でいくつかの環境で試したところ、スレッドが1つの場合は Paralell Mode を用いないほうが、若干速い。 → #ParalellModeMemo [編集]LLVM #(2011-02-02, 2012-09-25)
OpenMP Multi-Threaded Template Library #(2011-02-18) C++ の STL (Standard Template Library) の algorithm (#include <algorithm>) などを OpenMP 化したライブラリ。 「Common Versatile Multi-purpose Library for C++」の一部でもある。 [編集]HPC++ Parallel Standard Template Library (PSTL) #(2012-09-24) [編集]Web #
書籍 #[編集]ツール #[編集]メモ #[編集]GNU libc++ Parallel Mode #(2012-09-17, 2012-09-19) [編集]Ubuntu 11.10 64bit (on VMware Workstation), 1,2,4 threads #(2012-09-17, 2012-09-19) Ubuntu 11.10 64bit (on VMware Workstation), 2-thread / 4-theead で試してみた。 2-thread のときの性能が 3倍近い (Q9550 で 2.919倍、3930X で 2.789 倍) になる原因はわからない。 VMware で動かしているため、タイマの精度に問題があるのか?、それともメモリアクセスパターンが異なるだろうからキャッシュミスが減ったとか? 計測用プログラム(ソースコード) parallel_libstdcpp.cpp:
/* -*- coding: utf-8 mode: cpp -*- Linux, Cygwin $ g++ -Wall -Wextra parallel_libstdcpp.cpp -lrt -fopenmp -o explicit_parallel $ g++ -Wall -Wextra -D_GLIBCXX_PARALLEL parallel_libstdcpp.cpp -fopenmp -o implicit_parallel TDM64-GCC: $ g++ -Wall -Wextra parallel_libstdcpp.cpp -fopenmp -o explicit_parallel $ g++ -Wall -Wextra -D_GLIBCXX_PARALLEL parallel_libstdcpp.cpp -fopenmp -o implicit_parallel */ #include <algorithm> #include <parallel/algorithm> #include <vector> #include <iostream> #include <cstdlib> #include <ctime> //#include <random> #if defined _WIN32 || defined _WIN64 || defined _MSC_VER #include <windows.h> #include <psapi.h> double get_counter_sec() { LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); LARGE_INTEGER time; QueryPerformanceCounter(&time); return static_cast<double>(time.QuadPart) / freq.QuadPart; } #elif defined __unix__ #include <sys/types.h> #include <unistd.h> double get_counter_sec() { timespec ts; clock_gettime(CLOCK_REALTIME, &ts); return ts.tv_sec + ts.tv_nsec / double(1000*1000*1000); } #endif int main(int, char *[]) { srand(0); // std::mt19937 engine(0); // std::uniform_int<int> distribution(0, 65535); const size_t ARRAY_SIZE = 1024 * 1024; std::cout << "ARRAY_SIZE = " << ARRAY_SIZE << std::endl; std::vector<int> s; s.reserve(ARRAY_SIZE); for (size_t i = 0; i < ARRAY_SIZE; ++i) { s.push_back( int((rand() >> 2) % 65536) ); // s.push_back(distribution(engine)); } for (int i = 0; i < 3; ++i) { std::vector<int> v(s); const double start = get_counter_sec(); std::sort(v.begin(), v.end()); const double end = get_counter_sec(); std::cout << "std::sort(): elapsed = " << (end - start) << std::endl; } for (int i = 0; i < 3; ++i) { // Explicitly force a call to parallel sort. std::vector<int> v(s); const double start = get_counter_sec(); __gnu_parallel::sort(v.begin(), v.end()); const double end = get_counter_sec(); std::cout << "__gnu_parallel::sort(): elapsed = " << (end - start) << std::endl; } return 0; } このプログラムを使って、次の条件を変えて計測する:
libstdc++ と g++ のバージョン: $ dpkg -l | grep libstdc++6 ii libstdc++6 4.6.1-9ubuntu3 GNU Standard C++ Library v3 ii libstdc++6-4.4-dev 4.4.6-11ubuntu2 GNU Standard C++ Library v3 (development files) ii libstdc++6-4.5-dev 4.5.3-9ubuntu1 The GNU Standard C++ Library v3 (development files) ii libstdc++6-4.6-dev 4.6.1-9ubuntu3 GNU Standard C++ Library v3 (development files) $ g++ --version g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ビルド: $ g++ -Wall -Wextra parallel_libstdcpp.cpp -lrt -fopenmp -o explicit_parallel $ g++ -Wall -Wextra -D_GLIBCXX_PARALLEL parallel_libstdcpp.cpp -fopenmp -o implicit_parallel 実行 (Core2 Quad Q9550, VMware に4CPUコアを割り当て ARRAY_SIZE= 1024 * 1024) $ ./implicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.0879943 std::sort(): elapsed = 0.0848567 std::sort(): elapsed = 0.0844018 __gnu_parallel::sort(): elapsed = 0.0874939 __gnu_parallel::sort(): elapsed = 0.0869579 __gnu_parallel::sort(): elapsed = 0.0856276 $ ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.419451 std::sort(): elapsed = 0.417351 std::sort(): elapsed = 0.420393 __gnu_parallel::sort(): elapsed = 0.0866299 __gnu_parallel::sort(): elapsed = 0.08391 __gnu_parallel::sort(): elapsed = 0.0792465 $ OMP_NUM_THREADS=2 ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.421517 std::sort(): elapsed = 0.419009 std::sort(): elapsed = 0.425709 __gnu_parallel::sort(): elapsed = 0.155574 __gnu_parallel::sort(): elapsed = 0.152963 __gnu_parallel::sort(): elapsed = 0.151587 $ OMP_NUM_THREADS=1 ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.422655 std::sort(): elapsed = 0.425394 std::sort(): elapsed = 0.424165 __gnu_parallel::sort(): elapsed = 0.471778 __gnu_parallel::sort(): elapsed = 0.475645 __gnu_parallel::sort(): elapsed = 0.474769 実行 (Core i7 3980X, VMware に2CPUコアを割り当て, ARRAY_SIZE = 1024 * 1024) $ ./implicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.106128 std::sort(): elapsed = 0.105796 std::sort(): elapsed = 0.104501 __gnu_parallel::sort(): elapsed = 0.104554 __gnu_parallel::sort(): elapsed = 0.104465 __gnu_parallel::sort(): elapsed = 0.104423 $ ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.286969 std::sort(): elapsed = 0.28658 std::sort(): elapsed = 0.286289 __gnu_parallel::sort(): elapsed = 0.105846 __gnu_parallel::sort(): elapsed = 0.105538 __gnu_parallel::sort(): elapsed = 0.104874 $ OMP_NUM_THREADS=1 ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.288237 std::sort(): elapsed = 0.288404 std::sort(): elapsed = 0.287212 __gnu_parallel::sort(): elapsed = 0.331541 __gnu_parallel::sort(): elapsed = 0.332141 __gnu_parallel::sort(): elapsed = 0.331636 (2012-09-19) std::sort だけ(std_sort.cpp)、__gnu_parallel::sortだけ (parallel_sort.cpp) のコードを用意してビルドし、Cachegrind してみた。 refs も misses も桁は同じだが……。 ちなみに、KCachegrind で調べると、 __gnu_cxx::__normal_iterator<> と __memmove_ssse3_back (たぶん std::vector<int> v(s); で使ってる) が、refs も misses も多い。これ以上はライブラリソースコード見たほうがよいだろうから、当面は追求しない。 $ valgrind --tool=cachegrind ./std_sort ==2274== Cachegrind, a cache and branch-prediction profiler ==2274== Copyright (C) 2002-2010, and GNU GPL'd, by Nicholas Nethercote et al. ==2274== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info ==2274== Command: ./std_sort ==2274== ARRAY_SIZE = 1048576 std::sort(): elapsed = 14.553 std::sort(): elapsed = 14.5423 std::sort(): elapsed = 14.5295 ==2274== ==2274== I refs: 4,324,793,723 ==2274== I1 misses: 2,329 ==2274== LLi misses: 2,315 ==2274== I1 miss rate: 0.00% ==2274== LLi miss rate: 0.00% ==2274== ==2274== D refs: 2,798,578,362 (1,678,353,195 rd + 1,120,225,167 wr) ==2274== D1 misses: 2,663,281 ( 2,394,202 rd + 269,079 wr) ==2274== LLd misses: 458,693 ( 230,066 rd + 228,627 wr) ==2274== D1 miss rate: 0.0% ( 0.1% + 0.0% ) ==2274== LLd miss rate: 0.0% ( 0.0% + 0.0% ) ==2274== ==2274== LL refs: 2,665,610 ( 2,396,531 rd + 269,079 wr) ==2274== LL misses: 461,008 ( 232,381 rd + 228,627 wr) ==2274== LL miss rate: 0.0% ( 0.0% + 0.0% ) $ valgrind --tool=cachegrind ./parallel_sort ==2260== Cachegrind, a cache and branch-prediction profiler ==2260== Copyright (C) 2002-2010, and GNU GPL'd, by Nicholas Nethercote et al. ==2260== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info ==2260== Command: ./parallel_sort ==2260== ARRAY_SIZE = 1048576 __gnu_parallel::sort(): elapsed = 10.1422 __gnu_parallel::sort(): elapsed = 9.92051 __gnu_parallel::sort(): elapsed = 9.91161 ==2260== ==2260== I refs: 2,902,486,501 ==2260== I1 misses: 5,332 ==2260== LLi misses: 5,027 ==2260== I1 miss rate: 0.00% ==2260== LLi miss rate: 0.00% ==2260== ==2260== D refs: 1,908,302,435 (1,196,395,228 rd + 711,907,207 wr) ==2260== D1 misses: 3,016,637 ( 2,346,325 rd + 670,312 wr) ==2260== LLd misses: 1,039,349 ( 431,922 rd + 607,427 wr) ==2260== D1 miss rate: 0.1% ( 0.1% + 0.0% ) ==2260== LLd miss rate: 0.0% ( 0.0% + 0.0% ) ==2260== ==2260== LL refs: 3,021,969 ( 2,351,657 rd + 670,312 wr) ==2260== LL misses: 1,044,376 ( 436,949 rd + 607,427 wr) ==2260== LL miss rate: 0.0% ( 0.0% + 0.0% )[編集] Cygwin 1.7.16-1 (ligstdc++ 4.5.3-3) #(2012-09-19) 計測に使ったプログラムは ./#Ubuntu1110_64_VM と同じ。
$ g++ --version g++ (GCC) 4.5.3 Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ cygcheck -cd | grep stdc libstdc++6 4.5.3-3 libstdc++6-devel 4.5.3-3 $ cygcheck -cd cygwin Cygwin Package Information Package Version cygwin 1.7.16-1 $ g++ -Wall -Wextra parallel_libstdcpp.cpp -lrt -fopenmp -o explicit_parallel $ g++ -Wall -Wextra -D_GLIBCXX_PARALLEL parallel_libstdcpp.cpp -fopenmp -o implicit_parallel $ cat /proc/cpuinfo | grep model | sort -u model name : Intel(R) Core(TM)2 Duo CPU E8500 @ 3.16GHz model : 23 $ ./implicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.109375 std::sort(): elapsed = 0.125 std::sort(): elapsed = 0.140625 __gnu_parallel::sort(): elapsed = 0.125 __gnu_parallel::sort(): elapsed = 0.125 __gnu_parallel::sort(): elapsed = 0.140625 $ ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.34375 std::sort(): elapsed = 0.34375 std::sort(): elapsed = 0.34375 __gnu_parallel::sort(): elapsed = 0.125 __gnu_parallel::sort(): elapsed = 0.125 __gnu_parallel::sort(): elapsed = 0.140625 $ OMP_NUM_THREADS=1 ./explicit_parallel ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.34375 std::sort(): elapsed = 0.34375 std::sort(): elapsed = 0.34375 __gnu_parallel::sort(): elapsed = 0.390625 __gnu_parallel::sort(): elapsed = 0.40625 __gnu_parallel::sort(): elapsed = 0.390625[編集] TDM-GCC (tdm64-gcc-4.6.1, tdm64-gcc-4.7.1-2) #(2012-09-21) 計測に使ったプログラムは ./#Ubuntu1110_64_VM と同じ。 TDM64-GCC-4.6.1: C:> C:\TDM64-GCC-4.6.1\mingwvars.bat Setting up environment for using MinGW with GCC from C:\TDM64-GCC-4.6.1\. C:> g++ --version g++ (tdm64-1) 4.6.1 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. C:> g++ -m32 -Wall -Wextra parallel_libstdcpp.cpp -fopenmp -o explicit_parallel C:> g++ -m32 -Wall -Wextra -D_GLIBCXX_PARALLEL parallel_libstdcpp.cpp -fopenmp -o implicit_parallel C:> implicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.120652 std::sort(): elapsed = 0.12115 std::sort(): elapsed = 0.10869 __gnu_parallel::sort(): elapsed = 0.11732 __gnu_parallel::sort(): elapsed = 0.108439 __gnu_parallel::sort(): elapsed = 0.109112 C:> explicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.320039 std::sort(): elapsed = 0.318552 std::sort(): elapsed = 0.319395 __gnu_parallel::sort(): elapsed = 0.119199 __gnu_parallel::sort(): elapsed = 0.1221 __gnu_parallel::sort(): elapsed = 0.109956 C:> set OMP_NUM_THREADS=1 C:> explicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.318986 std::sort(): elapsed = 0.319036 std::sort(): elapsed = 0.31948 __gnu_parallel::sort(): elapsed = 0.365821 __gnu_parallel::sort(): elapsed = 0.366088 __gnu_parallel::sort(): elapsed = 0.367129 TDM64-GCC-4.7.1-2: C:> C:\TDM64-GCC-4.7.1\mingwvars.bat Setting up environment for using MinGW with GCC from c:\TDM64-GCC-4.7.1\. C:> g++ --version g++ (tdm64-1) 4.7.1 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. C:> g++ -m32 -Wall -Wextra parallel_libstdcpp.cpp -fopenmp -o explicit_parallel C:> g++ -m32 -Wall -Wextra -D_GLIBCXX_PARALLEL parallel_libstdcpp.cpp -fopenmp -o implicit_parallel C:> implicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.123822 std::sort(): elapsed = 0.124058 std::sort(): elapsed = 0.110214 __gnu_parallel::sort(): elapsed = 0.119833 __gnu_parallel::sort(): elapsed = 0.110097 __gnu_parallel::sort(): elapsed = 0.12179 C:> explicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.311162 std::sort(): elapsed = 0.310624 std::sort(): elapsed = 0.310892 __gnu_parallel::sort(): elapsed = 0.121613 __gnu_parallel::sort(): elapsed = 0.124109 __gnu_parallel::sort(): elapsed = 0.110146 C:> set OMP_NUM_THREADS=1 C:> explicit_parallel.exe ARRAY_SIZE = 1048576 std::sort(): elapsed = 0.311342 std::sort(): elapsed = 0.310794 std::sort(): elapsed = 0.31138 __gnu_parallel::sort(): elapsed = 0.361351 __gnu_parallel::sort(): elapsed = 0.360332 __gnu_parallel::sort(): elapsed = 0.362469[編集] Microsoft Visual Studio (2005,2008,2010,2012) #(2011-01-09) (1) OpenMP は、Visual Studio 2005,2008,2010 の Professional Edition と、VisualStudio 2012 (Visaul Studio 2012 Express for Desktop を含む) でサポートされている。 これらの環境では、 Visual Studio がインストールされていれば、OpenMPを用いるプログラムをビルドできる。 OpenMP を使うには、「プロジェクトのプロパティ→構成プロパティ→C/C++→言語→OpenMPのサポート (/openmp)」を有効にする。 (2) Visual Studio 2005, 2008 の Express Edition, Standard Edition では Windows SDK に含まれるヘッダファイルとライブラリ (Release版のみ。Debug版は含まれていない) を用いれば使える。 参考:
(3) Visual Studio 2010 の Express Edition では、対応する Windows SDK に OpenMP のファイルが含まれていないため、使えない。 (4) Visual Studio 2012 では、すべてのエディションで OpenMP が使える。 [編集]Visual Studio 2005 Standard Edition #
Visual Studio 2008 Express Edition, Standard Edition #
Visual Studio 2010 Express Edition #OpenMP は使えない。→ ./#memo_VisualStudio [編集]Visual Studio Express 2012 for Windows Desktop #(2012-09-18, 2012-09-20) Visual Studio 2012 では、すべてのエディションで OpenMP が使えるようになった:
確認事項:
調査用ソースコード (OpenMP-check.cpp): #include <iostream> #include <vector> #include <omp.h> int main() { using std::cout; using std::endl; #if defined _WIN64 // MEMO: _WIN64 とともに _WIN32 も定義されるので、先に _WIN64 を検査すること。 cout << "64bit (defined _WIN64)" << endl; #elif defined _WIN32 cout << "32bit (defined _WIN32)" << endl; #endif cout << "_MSC_VER = " << _MSC_VER << endl << "_OPENMP= " << _OPENMP << endl << "omp_get_num_procs()= " << omp_get_num_procs() << endl << "omp_get_max_threads()= " << omp_get_max_threads() << endl ; // 配列への代入を並列実行する。代入する値は「スレッド番号」 const int n_num = 32; std::vector<int> num(n_num); // このループを並列実行する #pragma omp parallel for for (int i = 0; i < n_num; ++i) { num[i] = omp_get_thread_num(); } // 代入された値(スレッド番号)を表示する for (size_t i = 0, s = num.size(); i < s; ++i) { cout << "num[" << i << "]= " << num[i] << endl; } return 0; } ビルドのオプションは、次の一箇所だけを変更した:
ビルドした実行ファイルがちゃんと 32bit/64bit 版かどうかを確認した。OK: C:> "%VS110COMNTOOLS%\vsvars32.bat" C:> dumpbin /headers Release\OpenMP-check.exe | findstr "machine" 14C machine (x86) 32 bit word machine C:> dumpbin /headers Debug\OpenMP-check.exe | findstr "machine" 14C machine (x86) 32 bit word machine C:> dumpbin /headers x64\Release\OpenMP-check.exe | findstr "machine" 8664 machine (x64) C:> dumpbin /headers x64\Debug\OpenMP-check.exe | findstr "machine" 8664 machine (x64) 実行結果 (CPU = Core2 Quad Q6600): C:> Release\OpenMP-check.exe 32bit (defined _WIN32) _MSC_VER = 1700 _OPENMP= 200203 omp_get_num_procs()= 4 omp_get_max_threads()= 4 ... (以下略) C:> Debug\OpenMP-check.exe 32bit (defined _WIN32) _MSC_VER = 1700 _OPENMP= 200203 omp_get_num_procs()= 4 omp_get_max_threads()= 4 ... (以下略) C:> x64\Release\OpenMP-check.exe 64bit (defined _WIN64) _MSC_VER = 1700 _OPENMP= 200203 omp_get_num_procs()= 4 omp_get_max_threads()= 4 ... (以下略) C:> x64\Debug\OpenMP-check.exe 64bit (defined _WIN64) _MSC_VER = 1700 _OPENMP= 200203 omp_get_num_procs()= 4 omp_get_max_threads()= 4 ... (以下略)[編集] Windows SDK と Visual Studio のOpenMP ヘッダファイル/ライブラリの位置と大きさ #(2011-01-13) Windows SDK 6.0, Windows SDK 7.0, Visual Studio 2010 Professional をインストールしたPCにて、omp.h, ompassem.h, vcomp.lib, vcompd.lib の位置などを調べた。
omp.h (dir /s "C:\Program Files\omp.h"): C:\Program Files\Microsoft SDKs\Windows\v6.0\VC\INCLUDE\omp.h 2006/12/02 00:46 5,310 C:\Program Files\Microsoft Visual Studio 9.0\VC\include\omp.h 2006/06/21 13:13 5,316 C:\Program Files\Microsoft Visual Studio 10.0\VC\include\omp.h 2009/08/31 02:35 2,431 ompassem.h: C:\Program Files\Microsoft Visual Studio 9.0\VC\include\ompassem.h 2008/07/29 04:13 948 vcomp.lib (dir /s "C:\Program Files\vcomp.lib"): C:\Program Files\Microsoft SDKs\Windows\v6.0\VC\LIB\vcomp.lib 2006/12/02 00:46 26,812 C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\vcomp.lib 2008/07/29 04:44 28,446 C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\amd64\vcomp.lib 2008/07/29 04:16 27,890 C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\vcomp.lib 2010/03/18 01:56 28,580 C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\amd64\vcomp.lib 2010/03/18 06:28 28,004 vcompd.lib (dir /s "C:\Program Files\vcompd.lib"): C:\Program Files\Microsoft SDKs\Windows\v6.0\VC\LIB\vcompd.lib 2006/12/02 00:46 26,946 C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\vcompd.lib 2008/07/29 04:44 28,574 C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\amd64\vcompd.lib 2008/07/29 04:16 27,998 C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\vcompd.lib 2010/03/18 01:56 28,686 C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\amd64\vcompd.lib 2010/03/18 06:28 28,130 C:> dir "c:\program files\common files\Merge Modules\*OpenMP*" ... c:\program files\common files\Merge Modules のディレクトリ 2010/03/19 04:44 60,416 Microsoft_VC100_DebugOpenMP_x64.msm 2010/03/19 07:24 60,416 Microsoft_VC100_DebugOpenMP_x86.msm 2010/03/19 03:06 51,712 Microsoft_VC100_OpenMP_x64.msm 2010/03/19 05:49 50,176 Microsoft_VC100_OpenMP_x86.msm 2009/07/12 01:58 136,704 Microsoft_VC80_DebugOpenMP_x86.msm 2009/07/12 01:58 133,632 Microsoft_VC80_DebugOpenMP_x86_x64.msm 2009/07/12 01:59 124,928 Microsoft_VC80_OpenMP_x86.msm 2009/07/12 01:59 131,584 Microsoft_VC80_OpenMP_x86_x64.msm 2007/11/07 03:38 112,128 Microsoft_VC90_DebugOpenMP_x86.msm 2007/11/07 07:21 112,640 Microsoft_VC90_DebugOpenMP_x86_x64.msm 2007/11/07 03:42 102,400 Microsoft_VC90_OpenMP_x86.msm 2007/11/07 07:26 103,424 Microsoft_VC90_OpenMP_x86_x64.msm 2009/07/12 01:58 90,624 policy_8_0_Microsoft_VC80_DebugOpenMP_x86.msm 2009/07/12 01:58 90,624 policy_8_0_Microsoft_VC80_DebugOpenMP_x86_x64.msm 2009/07/12 01:59 89,600 policy_8_0_Microsoft_VC80_OpenMP_x86.msm 2009/07/12 01:59 89,600 policy_8_0_Microsoft_VC80_OpenMP_x86_x64.msm 2007/11/07 04:30 75,776 policy_9_0_Microsoft_VC90_DebugOpenMP_x86.msm 2007/11/07 08:16 74,752 policy_9_0_Microsoft_VC90_DebugOpenMP_x86_x64.msm 2007/11/07 04:35 74,752 policy_9_0_Microsoft_VC90_OpenMP_x86.msm 2007/11/07 08:22 75,264 policy_9_0_Microsoft_VC90_OpenMP_x86_x64.msm 20 個のファイル 1,841,152 バイト[編集] サンプルコード(1) #OpenMP の以下の関数とpragmaを用いている
サンプルコード(2) 「parallel for」 #(2011-02-03) 参考:「インテル C/C++ コンパイラー OpenMP 活用ガイド」 pi_omp.c OpenMP なし: #include <cstdio> int main() { const int num_steps = 2 * 10000 * 10000; const double step = 1.0 / (double) num_steps; double sum = 0.0; for (int i = 0; i <= num_steps; i++) { const double x = (i - 0.5) * step; sum += 4.0 / (1.0 + x * x); } const double pi = step * sum; std::printf("PI=%lf\n", pi); return 0; } OpenMP化したソースコード
#include <cstdio> #ifdef _OPENMP #include <omp.h> #endif int main() { const int num_steps = 2 * 10000 * 10000; const double step = 1.0 / (double) num_steps; double sum = 0.0; #pragma omp parallel for reduction(+:sum) for (int i = 0; i <= num_steps; i++) { const double x = (i - 0.5) * step; sum += 4.0 / (1.0 + x * x); } const double pi = step * sum; std::printf("PI=%lf\n", pi); return 0; } コンパイルと実行 (Cygwin 1.7.7-1, g++ 4.3.4, Core2Duo (2C2T)) ★ OpenMP 無効 $ g++ -Wall -Wextra pi_omp.cpp -o pi && time ./pi pi_omp.cpp:13: 警告: ignoring #pragma omp parallel PI=3.141593 real 0m1.459s ★ user 0m1.483s sys 0m0.015s ★ OpenMP 有効 $ g++ -Wall -Wextra -fopenmp pi_omp.cpp -o pi_omp && time ./pi_omp PI=3.141593 real 0m0.755s ★ user 0m1.374s sys 0m0.015s 最大スレッド数を変更して実行 (環境変数 OMP_NUM_THREADS): $ export OMP_NUM_THREADS=2 $ time ./pi_omp PI=3.141593 real 0m0.717s ★ user 0m1.358s sys 0m0.000s $ export OMP_NUM_THREADS=1 $ time ./pi_omp PI=3.141593 real 0m1.413s ★ user 0m1.421s sys 0m0.015s[編集] サンプルコード(3) 「parallel sections」 #(2011-02-04) 参考:「インテル C/C++ コンパイラー OpenMP 活用ガイド」 pi_omp.c pi_section.cpp (負荷の大きい処理 (calc_pi()) を2つ実行する): #include <cstdio> double calc_pi(const int num_steps) { const double step = 1.0 / (double) num_steps; double sum = 0.0; for (int i = 0; i <= num_steps; i++) { const double x = (i - 0.5) * step; sum += 4.0 / (1.0 + x * x); } const double pi = step * sum; return pi; } int main() { const double pi_1 = calc_pi(1 * 10000 * 10000); const double pi_2 = calc_pi(2 * 10000 * 10000); std::printf("PI_1=%lf\n", pi_1); std::printf("PI_2=%lf\n", pi_2); return 0; } pi_section をビルドして、実行する: $ g++ -Wall -Wextra pi_section.cpp -o pi_section && time ./pi_section PI_1=3.141593 PI_2=3.141593 real 0m2.113s ★ user 0m2.139s sys 0m0.000s pi_omp_section.cpp (OpenMPでcalc_pi()を2つ同時に実行するように修正): #include <cstdio> #ifdef _OPENMP #include <omp.h> #endif double calc_pi(const int num_steps) { const double step = 1.0 / (double) num_steps; double sum = 0.0; for (int i = 0; i <= num_steps; i++) { const double x = (i - 0.5) * step; sum += 4.0 / (1.0 + x * x); } const double pi = step * sum; return pi; } int main() { double pi_1; double pi_2; #pragma omp parallel sections { #pragma omp section pi_1 = calc_pi(1 * 10000 * 10000); #pragma omp section pi_2 = calc_pi(2 * 10000 * 10000); } std::printf("PI_1=%lf\n", pi_1); std::printf("PI_2=%lf\n", pi_2); return 0; } pi_omp_section をビルド、実行する: $ g++ -Wall -Wextra -fopenmp pi_omp_section.cpp -o pi_omp_section && time ./pi_omp_section PI_1=3.141593 PI_2=3.141593 real 0m1.418s ★ user 0m2.077s sys 0m0.015s |