簡體   English   中英

在C#中使用並行編程

[英]Using parallel programming in 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它是標准的.NET集合BitArray的修改版本:

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 -這是5個不同JIBitArray二進制向量的數組,長度為128 + 96 = 224位。

但是我在計算時得到了System.AggregateExceptionSystem.ArgumentOutOfRangeException

我使用TPL是因為我需要使用不同的輸入參數執行2 ^ 20個任務( bits具有2 ^ 20個元素)

有人可以解釋什么地方不對嗎?

一個問題是您沒有捕獲循環變量i。 到內部任務執行時,我已經是5。

但是您似乎也沒有等待內部任務的結果。 為什么不將內部任務Task<bool>以便獲得(並等待)其結果?

同樣,按照您的父任務的說法,這毫無意義,如果您要做的就是啟動其他任務(只要其中沒有長時間運行的計算),則只需使用一種方法即可。 如果您希望它有用,它將等待子任務完成,然后返回合並的結果。

使用Parallel.ForEach將使此代碼更簡單,並且更有可能實現您要執行的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM