Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>dan's answer will work and is a correct way to use <code>Parallel.For</code>, but I went through the trouble of profiling the code and I think you'll find that parallelising this won't make it any faster. Each <code>Parellel.For</code> makes several new threads, usually more than three, so with 3 nested <code>Parellel.For</code>s you will have have <em>at least</em> 3^3 (27) threads, which is more way more than the number of logical processors on any machine. The extra threads will if anything add an overhead and slow it down.</p> <p>So why not just have one <code>Parallel.For</code> and 2 ordinary <code>for</code> loops - this will mean that there are around 3-4 threads which will work great on a dual or quad core machine. Like this method:</p> <pre><code>static void Test2(int[] a) { int N = a.Length; int total = 0; Object locker = new object(); Parallel.For(0, N, i =&gt; { for (int j = i + 1; j &lt; N; ++j) for (int k = j + 1; k &lt; N; ++k) if (a[i] + a[j] + a[k] == 30) lock(locker) total++; }); } </code></pre> <p>Take the following code used to profile both methods:</p> <pre><code>class Program { static void Main(string[] args) { Random r = new Random(); int[] arr = new int[100]; arr = arr.Select(i =&gt; r.Next(-30, 30)).ToArray(); Profile(Test0, arr, 20); Profile(Test1, arr, 20); Profile(Test2, arr, 20); Console.WriteLine("Test0: {0} ms", Profile(Test0, arr, 100).TotalMilliseconds); Console.WriteLine("Test1: {0} ms", Profile(Test1, arr, 100).TotalMilliseconds); Console.WriteLine("Test2: {0} ms", Profile(Test2, arr, 100).TotalMilliseconds); Console.ReadLine(); } static void Test0(int[] a) { int N = a.Length; int total = 0; for (int i = 0; i &lt; N; ++i) for (int j = i + 1; j &lt; N; ++j) for (int k = j + 1; k &lt; N; ++k) if (a[i] + a[j] + a[k] == 30) total++; } static void Test1(int[] a) { int N = a.Length; int total = 0; Object locker = new object(); Parallel.For(0, N, i =&gt; Parallel.For(i+1, N, j =&gt; Parallel.For(j+1, N, k =&gt; { if (a[i] + a[j] + a[k] == 30) lock(locker) total++; }))); } static void Test2(int[] a) { int N = a.Length; int total = 0; Object locker = new object(); Parallel.For(0, N, i =&gt; { for (int j = i + 1; j &lt; N; ++j) for (int k = j + 1; k &lt; N; ++k) if (a[i] + a[j] + a[k] == 30) lock(locker) total++; }); } static TimeSpan Profile&lt;T&gt;(Action&lt;T&gt; action, T param, int repeats) { Stopwatch s = new Stopwatch(); for (int i = 0; i &lt; repeats; i++) { s.Start(); action(param); s.Stop(); } return new TimeSpan(s.ElapsedTicks/repeats); } } </code></pre> <p>This yields these results for average execution time for each method: (in Release mode, using .Net 4.0, on a quad core Intel Core i5 machine):</p> <pre><code>Test0: 0.2544 ms Test1: 3.3433 ms Test2: 0.1391 ms </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload