Мне нужно выполнить один метод с разными параметрами параллельно (используя 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.AggregateException
и System.ArgumentOutOfRangeException
, в то время как вычисления.
Я использую TPL, потому что мне нужно выполнить 2^20 задач с различными входными параметрами (bits
имеет 2^20 элементов)
Может кто-нибудь объяснить, что это не так?
Привет! Это много кода. Являются ли исключения из-за параллельной обработки? Сколько задач выполняется одновременно? Проверяются ли алгоритмы и работают ли они в непараллельной среде? Возможно, вы должны определить проблему немного лучше, чтобы получить здесь хорошие ответы ;-) – Stefan
'Oracle (биты JIBitArray, int rounds, int [] weak_bits_positions)' - работает корректно в непараллельном режиме. Я вынужден использовать TPL, потому что оценка векторов 2^20 по методу «Oracle» занимает около 7 часов – storojs72
Одна из проблем заключается в том, что вы не захватываете переменную цикла 'i'. К тому времени, когда выполняется внутренняя задача, 'i' уже 5. –