2015-06-14 82 views
0

我需要并行执行一个不同参数的方法(使用c#)。在C#中使用并行编程

我使用的指令从这里:

http://www.codeproject.com/Articles/189374/The-Basics-of-Task-Parallelism-via-C

但在地方的Sum(100)Sum(200)Sum(300)我要执行我有点复杂方法Oracle(JIBitArray bits, int rounds, int[] weak_bits_positions)Grain类的

代码片段:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace GrainApproximations 
{ 
    class Grain 
    { 
     JIBitArray NFSR; 
     JIBitArray LFSR; 

     JIBitArray key; 
     const int keysize = 128; 

     JIBitArray iv; 
     const int ivsize = 96; 

     public void Init(JIBitArray key, JIBitArray iv, int rounds) 
     { 
      this.key = key; 
      this.iv = iv; 

      NFSR = new JIBitArray(keysize); 
      LFSR = new JIBitArray(keysize); 

      /* load registers */ 
      //fill NFSR bits with key bits 
      for (int i = 0; i < keysize; ++i) 
      { 
       NFSR.Set(i, this.key.Get(i)); 
      } 

      for (int i = 0; i < ivsize; ++i) 
      { 
       LFSR.Set(i, this.iv.Get(i)); 
      } 

      //96 < i < 128 bits of LFSR - filling with 1 
      for (int i = ivsize; i < keysize; i++) 
      { 
       LFSR.Set(i, true); 
      } 

      /* do initial clockings */ 
      bool outbit; 
      bool Lbit; 
      bool Nbit; 

      for (int i = 0; i < rounds; ++i) 
      { 
       outbit = grain_keystream(); 

       Lbit = LFSR.Get(127); 
       Nbit = NFSR.Get(127); 

       LFSR.Set(127, outbit^Lbit); 
       NFSR.Set(127, outbit^Nbit); 
      } 

     } 

     private bool grain_keystream() 
     { 
      bool outbit = NFSR.Get(2)^NFSR.Get(15)^NFSR.Get(36)^ NFSR.Get(45)^NFSR.Get(64)^NFSR.Get(73)^NFSR.Get(89)^LFSR.Get(93)^(NFSR.Get(12) & LFSR.Get(8))^(LFSR.Get(13) & LFSR.Get(20))^(NFSR.Get(95) & LFSR.Get(42))^(LFSR.Get(60) & LFSR.Get(79))^(NFSR.Get(12) & NFSR.Get(95) & LFSR.Get(95)); 
      bool Nbit = LFSR.Get(0)^NFSR.Get(0)^NFSR.Get(26)^NFSR.Get(56)^NFSR.Get(91)^NFSR.Get(96)^(NFSR.Get(3) & NFSR.Get(67))^(NFSR.Get(11) & NFSR.Get(13))^(NFSR.Get(17) & NFSR.Get(18))^(NFSR.Get(27) & NFSR.Get(59))^(NFSR.Get(40) & NFSR.Get(48))^(NFSR.Get(61) & NFSR.Get(65))^(NFSR.Get(68) & NFSR.Get(84)); 
      bool Lbit = LFSR.Get(0)^LFSR.Get(7)^LFSR.Get(38)^LFSR.Get(70)^LFSR.Get(81)^LFSR.Get(96); 

      NFSR = NFSR.ShiftLeft(1); 
      LFSR = LFSR.ShiftLeft(1); 

      NFSR.Set(keysize - 1, Nbit); 
      LFSR.Set(keysize - 1, Lbit); 

      return outbit; 
     } 

     public JIBitArray Generate_Gamma_Bits(int length_in_bits) 
     { 
      JIBitArray ret = new JIBitArray(length_in_bits); 

      for (int i = 0; i < length_in_bits; i++) 
      { 
       ret.Set(i, grain_keystream()); 
      } 
      return ret; 

     } 

     public JIBitArray Oracle(JIBitArray bits, int rounds, int[] weak_bits_positions) 
     { 
      JIBitArray key_bits = bits.SubJIBitArray(0, 128); 
      JIBitArray iv_bits = bits.SubJIBitArray(128, 96); 

      JIBitArray[] L_subspace = Build_L_subspace(iv_bits, weak_bits_positions); 

      for (int i = 0; i < weak_bits_positions.Length; i++) 
      { 
       iv_bits.Set(weak_bits_positions[i], false); 
      } 

      int count = 0; 

      bool outbit = false; 
      JIBitArray gamma = new JIBitArray(1); 

      for (int i = 0; i < L_subspace.Length; i++) 
      { 
       Init(key_bits, iv_bits.Xor(L_subspace[i]), rounds); 
       outbit = Generate_Gamma_Bits(1).Get(0); 

       if (outbit) 
       { 
        count++; 
       } 

       //Console.ReadLine(); 
      } 

      Console.Write("oracle:"); 
      Console.Write(count % 2); 

      return count % 2 == 1 ? new JIBitArray(new bool[] { true }) : new JIBitArray(new bool[] { false }); 
     } 

     public JIBitArray[] Build_L_subspace(JIBitArray iv_bits, int[] weak_bits) 
     { 
      JIBitArray[] L_subspace = new JIBitArray[(int)Math.Pow((double)2, (double)weak_bits.Length)]; 
      JIBitArray[] vectors = VectorTable(weak_bits.Length); 

      for (int i = 0; i < (int)Math.Pow((double)2, (double)weak_bits.Length); i++) 
      { 
       L_subspace[i] = new JIBitArray(iv_bits.Count); 

       for (int j = 0; j < weak_bits.Length; j++) 
       { 
        L_subspace[i].Set(weak_bits[j], vectors[i].Get(j)); 
       } 
      } 

      return L_subspace; 
     } 

     //build table of all vectors of k variables 
     public static JIBitArray[] VectorTable(int k) 
     { 
      int rows = (int)Math.Pow((double)2, (double)k); 
      bool[] tmp = new bool[k]; 
      JIBitArray[] result = new JIBitArray[rows]; 
      string x = string.Empty; 
      char[] characters = new char[0]; 
      bool[] vector = new bool[0]; 

      for (int i = 0; i < rows; i++) 
      { 
       x = Convert.ToString(i, 2); 
       x = x.PadLeft(k, '0'); 
       characters = x.ToCharArray(); 
       vector = new bool[characters.Length]; 

       for (int j = 0; j < characters.Length; j++) 
       { 
        if (characters[j] == '1') 
        { 
         vector[j] = true; 
        } 
        else 
        { 
         vector[j] = false; 
        } 
       } 
       result[i] = new JIBitArray(vector); 
      } 
      return result; 
     }   
    } 
} 

JIBitArray - 这是BitArray修改后的版本非标准.NET集合:

http://www.codeproject.com/Articles/14430/My-BitArray-Class

Main方法我试图执行:

Grain grain = new Grain(); 
Task<bool[]> parent = new Task<bool[]>(() => 
     { 
      var results = new bool[5]; // Create an array for the results 

      // This tasks creates and starts 3 child tasks 

      for (int i = 0; i < results.Length; i++) 
      { 
       new Task(() => results[i] = grain.Oracle(bits[i], rounds, weak_bits).Get(0), TaskCreationOptions.AttachedToParent).Start(); 
      } 

      // Returns a reference to the array 
      // (even though the elements may not be initialized yet) 
      return results; 
     }); 

     // When the parent and its children have 
     // run to completion, display the results 
     var cwt = parent.ContinueWith(parentTask => 
          Array.ForEach(parentTask.Result, Console.WriteLine)); 

     // Start the parent Task so it can start its children 
     parent.Start(); 

     cwt.Wait(); // For testing purposes 

其中bits - 它是具有128 + 96 = 224比特长度的5个不同的JIBitArray二进制向量的阵列。

但我得到System.AggregateExceptionSystem.ArgumentOutOfRangeException,而计算。

我使用TPL,因为我需要用不同的输入参数(bits有2^20种元素)执行2^20个任务

有人可以解释什么是错的?

+0

嗨!这是很多代码。由于并行处理,是否有例外情况?同时运行多少个任务?算法是否经过测试,并且它们是否在非并行环境中工作?也许你应该找出更多的问题来获得一些好的答案;-) – Stefan

+0

Oracle(JIBitArray bits,int rounds,int [] weak_bits_positions)' - 在非并行中正常工作。我被迫使用TPL,因为通过'Oracle'方法评估2^20向量大约需要7小时 – storojs72

+0

一个问题是您没有捕获循环变量'i'。当内部任务执行时,'i'已经是5. –

回答

1

一个问题是你没有捕获循环变量我。在执行内部任务时,我已经是5.

但是,您也似乎没有在等待内部任务结果。为什么不让内部任务成为Task<bool>,这样你就可以得到(并等待)其结果?另外,正如你所写的,你的父任务完全没有意义,如果你想要做的只是启动一些其他任务(你没有长时间运行的计算),那么就使用一个方法。如果你希望它有用,它会等待子任务完成,然后返回组合结果。

使用Parallel.ForEach会使此代码更简单,更有可能实现您正在尝试执行的操作。

+0

是的,我了解'Parallel.For'循环。但是很遗憾它给出了相同的解... – storojs72

+0

在我看来,对方法(对方法内部操作的意义 - 限制)有一些限制,可以放入'Parallel.For'构造中。 – storojs72

+0

当使用'Parallel.For'时,第一次迭代是正常的(首先出来的位的计算是正确的),但是它在第二次迭代中断裂。 谷歌帮不了多少... – storojs72