Чтобы продемонстрировать насколько элегантно С# позволяет организовать параллельные вычисления, реализуем классическую задачу поиска простых чисел в заданном диапазоне множества натуральных чисел.
Для начала, я создам функцию-расширение для класса целых чисел int, определяющую является ли число простым.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
static class IntUtilities { public static bool isSimple(this int Number) { double j = 2; bool Simple = true; while (j <= Number / 2) { if (Math.Floor(Number / j) == Number / j) { Simple = false; break; } j++; } return Simple; } } |
Функция isSimple обернута в статический класс и реализует нужный нам метод проверки, является ли число простым.
Следующим шагом создадим класс-источник целых чисел. Его особенностью является использование конструкции yield при создании списка, что позволит нам не развертывать весь массив тестируемых чисел одномоментно в памяти, а выдавать их по требованию программы.
|
class NumberSource { private int _maxValue; public NumberSource(int MaxValue) { _maxValue = MaxValue; } public IEnumerable<int> getList() { int i = 2; while (i < _maxValue) { yield return i++; } } } |
Для инициализации массива мы передаём верхнюю планку — MaxValue. Т.е. массив состоит из чисел [2 … MaxValue — 1].
На данном этапе мы подготовили массив и функцию, которая выполняет независимые вычисления с отдельным элементом этого массива. Т.е. есть все необходимые условия, чтобы по возможности использовать параллельные вычисления.
Одно-поточный вариант
Далее посмотрим как выглядит код, выполняющий вычисления в одном потоке, чтобы впоследствии сравнить с много-поточной версией кода.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
class Program { static void Main(string[] args) { int top = 150000; var NS = new NumberSource(top); // получаем список NS.getList() // используем расширение LINQ // для фильтрации списка .Where(num => num.isSimple()) // и его сортировки, .OrderBy(num => num) // преобразуем IEnumerable в List .ToList() // и выводим результат вычислений .ForEach(num => Console.WriteLine(num.ToString() + " is simple")); } } |
Для одно-поточной версии сортировка является лишней, т.к. числа поставляются итак в нужном порядке. Сортировка пригодится в многопоточной версии.
Параллельные вычисления
Сравните код показанный ранее со следующим:
|
class Program { static void Main(string[] args) { int top = 150000; var NS = new NumberSource(top); // получаем список NS.getList() // распараллеливаем дальнейшие операции .AsParallel() .Where(num => num.isSimple()) .OrderBy(num => num) .ToList() .ForEach(num => Console.WriteLine(num.ToString() + " is simple")); } } |
Мощное расширение AsParallel() в пространстве имен System.Linq прячет от нас все технические особенности того, как наш код превращается в многопоточный.
Мало букафф? Читайте есчо !
Июнь 28, 2022 г.
Что такое Xamarin - следует почитать отдельно. Вкратце, это платформа с идеологией .NET, позволяет писать код сразу для разных платформ - iOS, Android, Win. Меня интересовала возможность на знакомом языке (C#), написать что либо под Android.
Я ...
Читать
Июль 3, 2022 г.
Это часть статьи по опыту создания приложения с использованием C# Xamarin для Android платформы.
Canvas - это общий для разных платформ подход к работе с графикой, он обычно материализуется в специфичном для языка / платформы объекте, который так и ...
Читать