teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

update

2019/03/19 16:00

投稿

yohhoy
yohhoy

スコア6191

answer CHANGED
@@ -22,4 +22,22 @@
22
22
  }
23
23
  ```
24
24
 
25
- スレッド間をまたいで値(このケースではイテレータオブジェクト)を受け渡す場合、単に値を“コピー”するか、オブジェクトの有効範囲を注意深く制御した上で参照渡しを行なってください。
25
+ スレッド間をまたいで値(このケースではイテレータオブジェクト)を受け渡す場合、単に値を“コピー”するか、オブジェクトの有効範囲を注意深く制御した上で参照渡しを行なってください。
26
+
27
+ ----
28
+ > 現在は以下のように順番に各要素に処理を行っていますが、1つの処理の計算量が重く、独立して行える処理のため、マルチスレッドで行いたいと思いました。
29
+
30
+ C++17標準ライブラリ範囲内であれば、[並列アルゴリズム](https://en.cppreference.com/w/cpp/algorithm/for_each)が提供されます。ただし、ご利用中の各コンパイラ/ライブラリが対応済みかは別途ご確認ください。
31
+
32
+ ```c++
33
+ #include <algorithm>
34
+ #include <execution>
35
+
36
+ std::for_each(
37
+ std::execution::par, // スレッド並列処理を指示
38
+ std::begin(vec), std::begin(end), [&](auto&& e) {
39
+ // 1要素に対する処理
40
+ });
41
+ ```
42
+
43
+ 外部OSSライブラリの利用でもよければ、[Intel TBB](https://www.threadingbuildingblocks.org/)もオススメです。ライセンスもPermissiveです。

2

refinement

2019/03/19 16:00

投稿

yohhoy
yohhoy

スコア6191

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  > 配列の各要素を(同じ要素にアクセスすることはないとはいえ)別々のスレッドから変更することに問題はないかどうか。
2
2
 
3
- はい。`std::vector<T>`の異なる要素に対して別々スレッドからの変更操作の安全性は、C++標準ライブラリ仕様で保証されます。記事「[スレッドセーフという幻想と現実](https://yohhoy.hatenablog.jp/entry/2013/12/15/204116)」もご参考にください。
3
+ はい。`std::vector<T>`の異なる要素に対する別々スレッドからの変更操作の安全性は、C++標準ライブラリ仕様で保証されます。記事「[スレッドセーフという幻想と現実](https://yohhoy.hatenablog.jp/entry/2013/12/15/204116)」もご参考にください。
4
4
 
5
5
  > std::vector の配列の一部の参照を作る方法について。
6
6
 
@@ -9,7 +9,7 @@
9
9
  C++20からは、`std::vector`のような連続メモリ領域に対して部分区間を表す [`std::span`クラステンプレート](https://en.cppreference.com/w/cpp/container/span) が導入されます。本質的にはイテレータペアと等価ですが、“区間”を表す単一オブジェクトとして扱えるメリットはあります。
10
10
 
11
11
  ----
12
- 質問中のコード実装では、★箇所でダングリング参照による並行動作バグを引き起こします。イテレータ変数`begin`, `end`は「1回のforループイテーション中でのみ有効」すが、★では“参照”として別スレッド渡しています。つまり新しいスレッド処理を行うタイミングでは、既に該当イテレータオブジェクトが破棄されている **可能性** があり、意図しない不定動作やメモリ破壊などの不具合を引き起こします。
12
+ 質問中のコード実装では、★箇所でダングリング参照による並行動作バグを引き起こします。変数`begin`, `end`は「forループの各反復処理中でのみ有効なイテレータオブジェクトを指しますが、★では“参照”として別スレッドへと渡しています。つまり新しいスレッド処理を始めるタイミングでは、既に該当イテレータオブジェクトが破棄されている **可能性** があり、意図しない不定動作やメモリ破壊などの不具合を引き起こします。
13
13
 
14
14
  ```c++
15
15
  for (int i = 0; i < num_threads; ++i) {
@@ -22,4 +22,4 @@
22
22
  }
23
23
  ```
24
24
 
25
- スレッド間をまたいで値(このケースではイテレータ)を受け渡す場合、単に値を“コピー”するか、オブジェクトの有効範囲を注意深く制御した上で参照渡しを行なってください。
25
+ スレッド間をまたいで値(このケースではイテレータオブジェクト)を受け渡す場合、単に値を“コピー”するか、オブジェクトの有効範囲を注意深く制御した上で参照渡しを行なってください。

1

update

2019/03/19 15:53

投稿

yohhoy
yohhoy

スコア6191

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  > 配列の各要素を(同じ要素にアクセスすることはないとはいえ)別々のスレッドから変更することに問題はないかどうか。
2
2
 
3
- はい。`std::vector<T>`の異なる要素に対して別々スレッドからの変更操作の安全性は、C++標準ライブラリ仕様で保証されます。
3
+ はい。`std::vector<T>`の異なる要素に対して別々スレッドからの変更操作の安全性は、C++標準ライブラリ仕様で保証されます。記事「[スレッドセーフという幻想と現実](https://yohhoy.hatenablog.jp/entry/2013/12/15/204116)」もご参考にください。
4
4
 
5
5
  > std::vector の配列の一部の参照を作る方法について。
6
6