C# 用于查找数组中少数元素之和的并行代码(子问题)

C# 用于查找数组中少数元素之和的并行代码(子问题),c#,algorithm,data-structures,loops,mono,C#,Algorithm,Data Structures,Loops,Mono,我有以下C#代码片段: using System; class count { public static void Main() { int [] a = {-30, 30, -20, -10, 40, 0, 10, 5}; int i,j,k; int N=8; for (i=0; i < N; ++i) for (j=i+1; j < N; ++j) for (k=j+1; k < N; ++k) if (a[i] + a[

我有以下C#代码片段:

using System;

class count {
 public static void Main()
 {
  int [] a = {-30, 30, -20, -10, 40, 0, 10, 5};
  int i,j,k;
  int N=8;

  for (i=0; i < N; ++i)
   for (j=i+1; j < N; ++j)
    for (k=j+1; k < N; ++k)
     if (a[i] + a[j] + a[k] == 30)
      Console.WriteLine (a[i].ToString () + a[j].ToString() + a[k].ToString());

 }
}
使用系统;
班级人数{
公共静态void Main()
{
int[]a={-30,30,-20,-10,40,0,10,5};
int i,j,k;
int N=8;
对于(i=0;i
上面的程序所做的是,从数组A中找出三元组a1、a2、a3,这样三元组的总和就是30

我想知道如何使用C#Parallel.来进行求和计算


我知道这是一个面试问题,有比I,j,k循环更好的替代算法。但是,我只想了解如何使用C#的并行扩展有效地执行此操作

dan的答案会起作用,并且是使用
并行的正确方法。对于
,但是我经历了分析代码的麻烦,我想你会发现并行化并不会使它更快。每个
Parellel.For
都会生成几个新线程,通常超过三个,因此对于3个嵌套的
Parellel.For
s,您将拥有至少3^3(27)个线程,这比任何机器上的逻辑处理器数量都要多。额外的线程会增加开销并降低速度

那么,为什么不让一个
并行。对于
和两个普通
用于
循环-这意味着大约有3-4个线程可以在双核或四核机器上工作。像这样的方法:

static void Test2(int[] a)
{
    int N = a.Length;
    int total = 0;
    Object locker = new object();

    Parallel.For(0, N, i => 
    {
       for (int j = i + 1; j < N; ++j)
            for (int k = j + 1; k < N; ++k)
                if (a[i] + a[j] + a[k] == 30)
                    lock(locker)
                        total++; 
    });
}

+我完全同意。事实上,我会问这个作为面试问题,如果他们给了我丹的答案,我会扣分,因为这表明他们不明白“为什么”你应该使用paralelf,而只是“如何”使用paralelforkept,意思是自己写这样的答案,但太懒了。干得好,谢谢大家的回答。正如我提到的,我并不是真的在寻找一个完美的解决方案。但是想知道如何在C#中实现这一点。你的解决方案太棒了。谢谢大家。为什么不联锁。增量?
class Program
{
    static void Main(string[] args)
    {
        Random r = new Random();
        int[] arr = new int[100];
        arr = arr.Select(i => 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 < N; ++i)
            for (int j = i + 1; j < N; ++j)
                for (int k = j + 1; k < 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 => Parallel.For(i+1, N, j => Parallel.For(j+1, N, k =>
        {
            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 => 
        {
            for (int j = i + 1; j < N; ++j)
                for (int k = j + 1; k < N; ++k)
                    if (a[i] + a[j] + a[k] == 30)
                        lock(locker) 
                            total++;
        });
    }

    static TimeSpan Profile<T>(Action<T> action, T param, int repeats)
    {
        Stopwatch s = new Stopwatch();

        for (int i = 0; i < repeats; i++)
        {
            s.Start();
            action(param);
            s.Stop();
        }

        return new TimeSpan(s.ElapsedTicks/repeats);
    }
}
Test0: 0.2544 ms
Test1: 3.3433 ms
Test2: 0.1391 ms