質問内容
下記コードはなんの変哲もない普通の
整数同士のベクトルの内積を行う関数dotと
複数のcpuに作業を分担させて
計算を高速化させることを目論み実装された
内積関数dot_multi_threadの処理速度を
比較するためのコードです。
コードをコンパイルして実行してみましたが
dot_multi_threadでの計算が
dotよりかなり遅かったです。
こちらのサイトには
使用可能なプロセッサが複数ある場合、スレッドは使用可能なコアで同時に実行されます。
と記載されています。
なので下記コードでもdot_multi_thread関数内の
関数オブジェクトparaがスレッドの数だけ同時に動いて
計算が速くなるような気がしたのですが
結果は予想外なものでした。
なぜdot_multi_thread関数での計算の方が
遅くなってしまったのでしょうか。
どうかご回答宜しくお願いいたします。
コード
c++
1#include <iostream> 2#include <iomanip> 3#include <thread> 4#include <mutex> 5#include <chrono> 6 7// divisible_byで割り切れる最もclose_to_numに近い整数を算出 8inline size_t round_up(const size_t close_to_num, const size_t divisible_by)noexcept 9{ 10 return divisible_by == 0 ? close_to_num : close_to_num + divisible_by - (close_to_num % divisible_by); 11} 12 13// threadを用いない内積 14inline long long dot(const size_t n, const long long* const a, const long long* const b)noexcept 15{ 16 long long result = 0; 17 for(size_t i = 0; i<n; ++i) result += a[i] * b[i]; 18 return result; 19} 20 21// threadを用いる内積 22long long dot_multi_thread(const size_t n, const long long* const a, const long long* const b, const unsigned thread_num)noexcept 23{ 24 size_t npt = n / thread_num; 25 long long result = 0; 26 std::mutex mtx; 27 28 // 並列で実行する関数オブジェクト 29 auto para = [&](const size_t n, const long long* const a, const long long* const b) 30 { 31 std::lock_guard<std::mutex> lock(mtx); 32 result += dot(n, a, b); 33 }; 34 35 for(size_t i = 0; i < thread_num; ++i) 36 { 37 std::thread(para, npt, a+npt*i, b+npt*i).join(); 38 } 39 40 return result; 41} 42 43int main() 44{ 45 const unsigned thread_num = std::thread::hardware_concurrency(); 46 //const unsigned thread_num = 2;// 使用するスレッド数 47 48 size_t size = 1234; 49 size_t true_size = round_up(size, thread_num); 50 51 auto* mem1 = new long long[true_size]; 52 auto* mem2 = new long long[true_size]; 53 54 for(unsigned i = 0; i<true_size; ++i) 55 { 56 if(i < size){ 57 mem1[i] = i; 58 mem2[i] = i; 59 }else 60 { 61 mem1[i] = 0; 62 mem2[i] = 0; 63 } 64 } 65 66 auto start_1 = std::chrono::system_clock::now(); 67 auto res1 = dot(true_size, mem1, mem2); 68 auto end_1 = std::chrono::system_clock::now(); 69 double time_1 = std::chrono::duration_cast<std::chrono::nanoseconds>(end_1-start_1).count(); 70 71 auto start_2 = std::chrono::system_clock::now(); 72 auto res2 = dot_multi_thread(true_size, mem1, mem2, thread_num); 73 auto end_2 = std::chrono::system_clock::now(); 74 double time_2 = std::chrono::duration_cast<std::chrono::nanoseconds>(end_2-start_2).count(); 75 76 delete[] mem1; 77 delete[] mem2; 78 79 std::cout << "--------------------------------------------------------------" << std::endl; 80 std::cout << std::fixed << std::setprecision(20); 81 std::cout << "単一スレッド :" << res1 << std::endl; 82 std::cout << "マルチスレッド :" << res2 << std::endl; 83 84 std::cout << "--------------------------------------------------------------" << std::endl; 85 std::cout << std::fixed << std::setprecision(0); 86 std::cout << "単一スレッド :" << time_1 << "ナノ秒" << std::endl; 87 std::cout << "マルチスレッド :" << time_2 << "ナノ秒" << std::endl; 88 89 return 0; 90}
実行結果
terminal
1-------------------------------------------------------------- 2単一スレッド :625599129 3マルチスレッド :625599129 4-------------------------------------------------------------- 5単一スレッド :9901ナノ秒 6マルチスレッド :1247756ナノ秒
開発環境の備考
種類 | 名前 | バージョン | 備考 |
---|---|---|---|
os | Linux Mint | 20 | - |
cpu | Intel© Core™ i7-7700 CPU @ 3.60GHz × 4 | - | コア数4 スレッド数8 |
コンパイラ | clang++ | 10 | コンパイルオプションに-pthreadを記載 |
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/11/10 08:18
2020/11/10 08:24
退会済みユーザー
2020/11/10 08:35
2020/11/10 08:38
2020/11/10 08:41
退会済みユーザー
2020/11/10 08:45
2020/11/10 08:50 編集
退会済みユーザー
2020/11/10 09:09
2020/11/10 10:14
退会済みユーザー
2020/11/10 11:38