回答編集履歴

5

文言の修正

2017/05/17 07:34

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -204,7 +204,7 @@
204
204
 
205
205
  しかし、通常私たちが使う計算式はそんなに長時間CPUを占有しないので、スレッド開始のコストが並列化のメリットを上回ってしまう。
206
206
 
207
- 例えば、最適化されたマップ探索アルゴリズムを持つゲームであれば単純に並列化しただけではパフォーマンス増加に繋がらない可能性は十分にあり得る。(メモリも沢山使うしね)
207
+ 例えば、い処理の一つにマップ探索アルゴリズムなどがげらるが、これにしたって最適化されていれば単純に並列化しただけではパフォーマンス増加に繋がらない可能性は十分にあり得る。(メモリも沢山使うしね)
208
208
 
209
209
 
210
210
 

4

文言の修正

2017/05/17 07:34

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -202,7 +202,7 @@
202
202
 
203
203
  このため、計算量がスレッド開始のコストを上回る計算量になって初めてマルチスレッドはコア数分の時間短縮を受けられる。
204
204
 
205
- しかし、通常私たちが使う計算式はそんなに長時間CPUを占有しないので、コンテキトスイのコストが並列化のメリットを上回ってしまう。
205
+ しかし、通常私たちが使う計算式はそんなに長時間CPUを占有しないので、スド開始のコストが並列化のメリットを上回ってしまう。
206
206
 
207
207
  例えば、最適化されたマップ探索アルゴリズムを持つゲームであれば単純に並列化しただけではパフォーマンス増加に繋がらない可能性は十分にあり得る。(メモリも沢山使うしね)
208
208
 

3

サンプルコードの追加

2017/05/17 07:33

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -43,3 +43,171 @@
43
43
  そういったものは並列化に向いてる。
44
44
 
45
45
  複数ファイル同時にダウンロードできるぐらいの性能がLANポートには十分あるし、シングルコアでも並列化することで高速化できる。
46
+
47
+
48
+
49
+ ---
50
+
51
+
52
+
53
+ 君のためにどうでもいいコードを書いてみた。
54
+
55
+ 十分にCPU計算処理が重たい場合、コア数分は高速化する。
56
+
57
+ しかし、短いCPU計算の場合、速度は劣化する。
58
+
59
+ ```C#
60
+
61
+ namespace ParallelSample
62
+
63
+ {
64
+
65
+ using System;
66
+
67
+ using System.Diagnostics;
68
+
69
+ using System.Linq;
70
+
71
+ using System.Threading.Tasks;
72
+
73
+
74
+
75
+ class Program
76
+
77
+ {
78
+
79
+ const int num = 100;
80
+
81
+
82
+
83
+ static void Main(string[] args)
84
+
85
+ {
86
+
87
+ if (args.Length != 1) return;
88
+
89
+
90
+
91
+ var start = long.Parse(args[0]);
92
+
93
+
94
+
95
+ var single = new Stopwatch();
96
+
97
+ var result_s = new bool[num];
98
+
99
+ single.Start();
100
+
101
+ foreach (var i in Enumerable.Range(0, num))
102
+
103
+ {
104
+
105
+ long value = start + i * 2;
106
+
107
+ result_s[i] = IsPrime(value);
108
+
109
+ }
110
+
111
+ single.Stop();
112
+
113
+
114
+
115
+ Console.WriteLine($"シングルスレッド : {single.ElapsedMilliseconds}ms");
116
+
117
+
118
+
119
+ var parallel = new Stopwatch();
120
+
121
+ var result_p = new bool[num];
122
+
123
+ parallel.Start();
124
+
125
+ Parallel.ForEach(Enumerable.Range(0, num), i =>
126
+
127
+ {
128
+
129
+ long value = start + i * 2;
130
+
131
+ result_p[i] = IsPrime(value);
132
+
133
+ });
134
+
135
+
136
+
137
+ parallel.Stop();
138
+
139
+ Console.WriteLine($"マルチスレッド : {parallel.ElapsedMilliseconds}ms");
140
+
141
+ }
142
+
143
+
144
+
145
+ // 全ての値で割ってみて、素数か判定するのを原始的に行うメソッド
146
+
147
+ static bool IsPrime(long n)
148
+
149
+ {
150
+
151
+ for (long i = 2; i < n; i++)
152
+
153
+ {
154
+
155
+ if (n % i == 0) return false;
156
+
157
+ }
158
+
159
+ return true;
160
+
161
+ }
162
+
163
+ }
164
+
165
+ }
166
+
167
+ ```
168
+
169
+
170
+
171
+ 結果は、i5-3470S@2.90GHzのPCで以下のようになった。
172
+
173
+ ```
174
+
175
+ > ParallelSample 10001
176
+
177
+ シングルスレッド : 2ms
178
+
179
+ マルチスレッド : 19ms
180
+
181
+
182
+
183
+ > ParallelSample 100001
184
+
185
+ シングルスレッド : 11ms
186
+
187
+ マルチスレッド : 21ms
188
+
189
+
190
+
191
+ > ParallelSample 10000001
192
+
193
+ シングルスレッド : 595ms
194
+
195
+ マルチスレッド : 207ms
196
+
197
+ ```
198
+
199
+
200
+
201
+ 原始的に素数判定を行っているため、素数の判定開始数値が大きくなると飛躍的にCPU処理時間が増える。
202
+
203
+ このため、計算量がスレッド開始のコストを上回る計算量になって初めてマルチスレッドはコア数分の時間短縮を受けられる。
204
+
205
+ しかし、通常私たちが使う計算式はそんなに長時間CPUを占有しないので、コンテキストスイッチのコストが並列化のメリットを上回ってしまう。
206
+
207
+ 例えば、最適化されたマップ探索アルゴリズムを持つゲームであれば単純に並列化しただけではパフォーマンス増加に繋がらない可能性は十分にあり得る。(メモリも沢山使うしね)
208
+
209
+
210
+
211
+ 仮にI/Oバウンドな処理を行っていたとしても、並列数を引き上げ過ぎると「待機の確認」に時間がかかりすぎてしまい、速度は低下することもあるし、並列化は扱いが難しいものだ。
212
+
213
+ 常に計測が必要ってことを覚えておいてもらえれば、とりあえずはいいんじゃないかな。

2

コードを一応追記したぞ

2017/05/17 07:30

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -6,7 +6,23 @@
6
6
 
7
7
  (2500個の要素4つの配列に分けて実行すれば別だが、割り込みによって2500個同時にデータの処理が終わるわけではないのは想像がつくよね。つまりムズイってことだ!)
8
8
 
9
- だから、IEnumerable<T>を単純に`AsParallel()`して、各メソッドに要素突っ込むぜ、コア全部使うぜ、これで最速だろ!なんて思っても、大体の場合早くならない。場合によっては遅くなる。
9
+ だから、`IEnumerable<T>`を単純に`AsParallel()`して、各メソッドに要素突っ込むぜ、コア全部使うぜ、これで最速だろ!なんて思っても、大体の場合早くならない。場合によっては遅くなる。
10
+
11
+
12
+
13
+ 例えば、下記のコードはDoSomethingがCPU-BOUNDだと簡単には早くならない。
14
+
15
+ ```C#
16
+
17
+ foreach (var item in items.AsParallel())
18
+
19
+ {
20
+
21
+ DoSomething(item);
22
+
23
+ }
24
+
25
+ ```
10
26
 
11
27
 
12
28
 

1

なんか最初のメソッドいらなかったから削除

2017/05/17 06:35

投稿

haru666
haru666

スコア1591

test CHANGED
@@ -1,37 +1,3 @@
1
- 非同期で下記のようなコードがあったとしよう。
2
-
3
-
4
-
5
- ```C#
6
-
7
- void SomeFunction
8
-
9
- {
10
-
11
- var task = HeavyTask();
12
-
13
-
14
-
15
- task.Wait(); // 非同期のタスクが終わるまで処理待ち
16
-
17
-
18
-
19
- // 処理完了を待ってなんかやる
20
-
21
- }
22
-
23
-
24
-
25
- Task HeavyTask()
26
-
27
- {
28
-
29
- }
30
-
31
- ```
32
-
33
-
34
-
35
1
  例えば重たい数式の計算だったり、メモリ上にロードされた全データのスキャンだったりみたいなのを非同期にラップしても、並列化した時精々最大でコア数分の軽量化にしかならない。それどころかスレッドをそれ以上作るとコンテキストスイッチ分動作速度が遅くなる。
36
2
 
37
3