简体   繁体   English

在C#中使用并行编程

[英]Using parallel programming in C#

I need to execute one method with different parameters in parallel (using c#). 我需要并行执行一个具有不同参数的方法(使用c#)。

I use instructions from here: 我从这里使用说明:

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

but in place of Sum(100) , Sum(200) , Sum(300) I want execute my a bit more complex method Oracle(JIBitArray bits, int rounds, int[] weak_bits_positions) . 但是我想代替我的Sum(100)Sum(200)Sum(300)执行我更复杂的方法Oracle(JIBitArray bits, int rounds, int[] weak_bits_positions)

Code snippet of Grain class: 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 - it's a modified version of standart .NET collection BitArray : JIBitArray它是标准的.NET集合BitArray的修改版本:

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

In Main method I try to execute: 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

where bits - it's an array of 5 different JIBitArray binary vectors with 128 + 96 = 224 bits length. 其中bits -这是5个不同JIBitArray二进制向量的数组,长度为128 + 96 = 224位。

But I get System.AggregateException and System.ArgumentOutOfRangeException , while computations. 但是我在计算时得到了System.AggregateExceptionSystem.ArgumentOutOfRangeException

I use TPL because I need to execute 2^20 tasks with different input parameters ( bits has 2^20 elements) 我使用TPL是因为我需要使用不同的输入参数执行2 ^ 20个任务( bits具有2 ^ 20个元素)

Can somebody explain what is wrong? 有人可以解释什么地方不对吗?

One issue is that you are not capturing the loop variable i. 一个问题是您没有捕获循环变量i。 By the time the inner task executes, i is already 5. 到内部任务执行时,我已经是5。

But you also do not appear to be waiting for the inner task results. 但是您似乎也没有等待内部任务的结果。 Why not make the inner task a Task<bool> so you can get (and wait for) its result? 为什么不将内部任务Task<bool>以便获得(并等待)其结果?

Also, as written your parent task is utterly pointless, just use a method if all you want to do is start some other Tasks (you have no long-running computation in there). 同样,按照您的父任务的说法,这毫无意义,如果您要做的就是启动其他任务(只要其中没有长时间运行的计算),则只需使用一种方法即可。 If you wanted it to be useful it would wait for the child Tasks to complete and then return the combined result. 如果您希望它有用,它将等待子任务完成,然后返回合并的结果。

Using Parallel.ForEach would make this code much simpler and more likely to achieve what you are trying to do. 使用Parallel.ForEach将使此代码更简单,并且更有可能实现您要执行的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM