Как изменить цикл для Parallel.For?C # - PullRequest
0 голосов
/ 12 апреля 2019

Я создал очень простое приложение, чтобы вычислить простые числа и затем написать их. Я хочу, чтобы он работал на всех ядрах, если пользователь выберет для вычисления, например, 1 000 000 ...

Как я могу преобразовать мой уже функционирующий цикл для запуска на всех ядрах? Я обнаружил, что есть Parallel.For, но я действительно не знаю, как конвертировать в это из моего существующего для цикла ...

    {
        bool isPrime = true;
        int fPrime = Convert.ToInt32(txt_input.Text);
        Application.DoEvents();

        for (int i = 2; i <= fPrime; i++)
        {
            for (int j = 2; j <= fPrime; j++)
            {

                if (i != j && i % j == 0)
                {
                    isPrime = false;
                    break;
                }

            }

            if (isPrime)
            {
                txt_result.Text = txt_result.Text + "..." + i;
            }
            isPrime = true;
        }

        txt_result.Text = txt_result.Text + Environment.NewLine + "Done";
    }

Ответы [ 3 ]

1 голос
/ 12 апреля 2019

Вы не сможете обновить пользовательский интерфейс, используя параллельный foreach, вы можете написать метод для возврата всех простых чисел

        private static List<int> PrimeNumbers(int input)
        {
            var bag = new ConcurrentBag<int>();
            Parallel.ForEach(Enumerable.Range(2, input), x =>
            {
                var isPrime = true;
                Parallel.ForEach(Enumerable.Range(2, input), (y, state) =>
                {
                    if ((x != y) && (x % y) == 0)
                    {
                        isPrime = false;
                        state.Break();
                    }
                });
                if (isPrime)
                    bag.Add(x);
            });

            return bag.AsEnumerable().OrderBy(x => x).ToList();
        }
1 голос
/ 12 апреля 2019

Лучший алгоритм обычно лучше худшего (но распараллеленного):

private static IEnumerable<int> Primes(int upTo) {
  if (upTo <= 1)
    yield break;

  yield return 2; // Special case: the only even prime

  List<int> primes = new List<int>() { };

  for (int number = 3; number <= upTo; number += 2) {
    int max = (int)(Math.Sqrt(number) + 0.5);
    bool isPrime = true;

    foreach (var div in primes)
      if (div > max)
        break;
      else if (number % div == 0) {
        isPrime = false;

        break;
      }

    if (isPrime) {
      primes.Add(number);

      yield return number;
    }
  }
}

...

txt_result.Text = string.Join(", ", Primes(1000000));

И вы получите

2, 3, 5, 7, 11, 13, 17, 19, 23, ... 999959, 999961, 999979, 999983

за доли секунды

0 голосов
/ 12 апреля 2019

Распараллеливания внешнего цикла должно быть достаточно.Вероятно, вы не собираетесь запускать программу на машине с большим количеством процессоров, чем внешние циклы!

Parallel.For(fromInclusive: 2, toExclusive: fPrime + 1, i =>
{
    for (int j = 2; j <= fPrime; j++)
    {

        if (i != j && i % j == 0)
        {
            isPrime = false;
            break;
        }

    }

    if (isPrime)
    {
        if (txt_result.InvokeRequired)
        {
            txt_result.Invoke((MethodInvoker)delegate { txt_result.Text = txt_result.Text + "..." + i; });
        }
        else
        {
            txt_result.Text = txt_result.Text + "..." + i;
        }
    }
    isPrime = true;
});
txt_result.Text = txt_result.Text + Environment.NewLine + "Done";
...