简体   繁体   中英

Using parallel programming in C#

I need to execute one method with different parameters in parallel (using c#).

I use instructions from here:

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) .

Code snippet of Grain class:

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 :

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

In Main method I try to execute:

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.

But I get System.AggregateException and System.ArgumentOutOfRangeException , while computations.

I use TPL because I need to execute 2^20 tasks with different input parameters ( bits has 2^20 elements)

Can somebody explain what is wrong?

One issue is that you are not capturing the loop variable i. By the time the inner task executes, i is already 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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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