Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
Что-то ищу информацию, и похоже ни PLINQ ни Parallel не умеют работать с async вызовами.

Мне нужно выполнить работу, которая включает в себя кучу последовательных обращений к БД, с мелкой обработкой промежуточных результатов. Т.е. куча IO Bound операций с маленькой каплей Cpu-Bound.

Ну к примеру вот тут пишут про PLINQ не умеет async (ответ дан 5 дней назад)
https://stackoverflow.com/a/51600479
It does not matter, that you try to await the AsyncTask(), because ForAll() gets a plain Action and does not await the result of your AsyncTask().

А тут пишут, что класс Parallel тоже не в курсе про async
https://stackoverflow.com/a/11565317
и там же предлагают задействовать TPL Dataflow - вот он мол умеет работать. Но в тоже время является очень тяжеловесным решением.


Так какой выход на текущем временном отрезке ?
16 авг 18, 17:39    [21644854]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4868
WaspNewCore,

1. Почему бы всю работу не сделать в БД?
2. Если у тебя 99,999% времени есть ожидание БД, а остальное обработка в приложении, то имеет смысл проверить, будет ли польза от параллельного обращение к БД, возможно встрянешь еще сильнее по скорости.
3. Если все же есть смысл ходить в БД параллельно, то просто запусти 10-100 потоков, пусть ждут наздоровье.
16 авг 18, 18:23    [21644902]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
ЕвгенийВ,

В том и суть. что нужно сделать в несколько потоков. Распараллелить и загрузить бд работой.
Бд же не умеет в несколько потоков работать ?
16 авг 18, 18:24    [21644904]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
ЕвгенийВ,

ну собственно я и хочу запустить 100 потоков - но, это правильно делать через async/await. А непосредственно генерацией этих сотен потоков занимаются PLINQ и Parallel. Но созданы они давно, и, как я понял, мелкософты не удосужились добавить в них поддержку async/await. А без них создавать сотни IO-Bound задач уже не комильфо.
16 авг 18, 18:27    [21644907]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4868
WaspNewCore
Бд же не умеет в несколько потоков работать ?

Ну тут смотря какая БД у тебя, odbc driver for dbf скорее всего не умеет :)
16 авг 18, 18:27    [21644908]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
ms sql.
Я имел ввиду - что я же не могу внутри T-SQL написать код который будет параллелить. Нету такого функционала в принципе. Это в C# я могу создавать потоки вручную, как и сколько мне надо.

Я могу лишь запустить сотню потоков работающих с бд из клиентского приложения.
16 авг 18, 18:30    [21644910]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4868
WaspNewCore
ЕвгенийВ,

ну собственно я и хочу запустить 100 потоков - но, это правильно делать через async/await. А непосредственно генерацией этих сотен потоков занимаются PLINQ и Parallel. Но созданы они давно, и, как я понял, мелкософты не удосужились добавить в них поддержку async/await. А без них создавать сотни IO-Bound задач уже не комильфо.

Исторически TPL была создана раньше async/await для распараллеливания вычислений, последние же нужны для асинхронности.
16 авг 18, 18:34    [21644914]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
ЕвгенийВ
3. Если все же есть смысл ходить в БД параллельно, то просто запусти 10-100 потоков, пусть ждут наздоровье.


Собственно тут есть два пути - правильный и не правильный.

не правильный это Task.Run (()=> SqlConnection.Query<Model>). В этом случае потоки будут простаивать в момент этого самого Query (пользуясь терминологией Dapper.Net).
правильно это что-то типа Parallel.ForEach (async x=> await SqlConnection.QueryAsync<Model>). В этом случае потоки будут освобождены на время QueryAsync. Но беда в том, что, как я понял, Parallel.ForEach (и Plinq) не знаю про async/await. Они могут только работать по неправильному пути.
16 авг 18, 18:34    [21644915]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
ЕвгенийВ,

Конечно TPL появилось раньше async/await.
Странно лишь то, что умные головы из Microsoft не добавляют поддержку в PLINQ и Parallel поддержку методов вида Parallel.ForEachAsync. При том что это сделали для любых маломальских классов типа File.GetAllTextAsync и прочего сразу с вводом async/await. Не пойму почему.

И даже альтернативы то не сделали. Кроме огромнейшего TPL Dataflow. Тянуть его в проект ради того, чтобы один раз воспользоватся аналогом Parallel.ForEachAsync как-то не хочется.

Вот и ищу, может есть какие-то другие альтернативы ? Кроме самописных велосипедов...
16 авг 18, 18:38    [21644917]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4868
WaspNewCore
ms sql.
Я имел ввиду - что я же не могу внутри T-SQL написать код который будет параллелить.

Ну почему же, можешь!

В T-SQL что делать решает оптимизатор и каждый простенький запрос может обслуживаться кучей потоков.
16 авг 18, 18:38    [21644918]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
WaspNewCore
Member

Откуда:
Сообщений: 179
ЕвгенийВ,

Если я правильно понимаю тут речь о распараллеливании селекта.
А мне нужно запустить некую T-SQL процедуру в нескольких экземлярах.
16 авг 18, 18:46    [21644925]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
WaspNewCore,
Сколько понаписал то.
Внутри потока создавай коннект и работай.
В чем проблема?
16 авг 18, 18:47    [21644927]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4868
WaspNewCore
При том что это сделали для любых маломальских классов типа File.GetAllTextAsync и прочего сразу с вводом async/await. Не пойму почему.


Это для тех случаев, когда Cpu-Bound не хватает, например в web highload приложении или для ГУЯ, дабы не блокировать его и не сильно напрягать программистов для этого.
16 авг 18, 18:49    [21644928]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4868
WaspNewCore
ЕвгенийВ,

Если я правильно понимаю тут речь о распараллеливании селекта.
А мне нужно запустить некую T-SQL процедуру в нескольких экземлярах.

Грубо говоря, если ты запустишь несколько раз долгоиграющую процедуру из разных окон например SSMS, то все запущенные будут исполняться параллельно.
16 авг 18, 18:52    [21644932]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2421
WaspNewCore
А тут пишут, что класс Parallel тоже не в курсе про async
https://stackoverflow.com/a/11565317
и там же предлагают задействовать TPL Dataflow - вот он мол умеет работать. Но в тоже время является очень тяжеловесным решением.

Там ниже предлагаются варианты на все возможные случаи "замеса" параллельности и асинхронности - RunWithMaxDegreeOfConcurrency и ForEachAsync.
16 авг 18, 19:04    [21644938]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2421
LR
Там ниже предлагаются варианты на все возможные случаи "замеса" параллельности и асинхронности - RunWithMaxDegreeOfConcurrency и ForEachAsync.

...и еще ниже - ParallelForEachAsync
16 авг 18, 19:06    [21644940]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
WaspNewCore
не правильный это Task.Run (()=> SqlConnection.Query<Model>).

Правильный:
Task.Run(()=> MyMetodAsync()
16 авг 18, 19:12    [21644950]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
hVostt
Member

Откуда:
Сообщений: 16313
WaspNewCore,

Кажется, что вы смешали мухи с котлетами.

Чтобы понять где косяк, надо просто понять одну простую вещь.
Код с асинхронными вызовами с точки зрения execution flow абсолютно синхронный.

В тоже время TPL это параллельный execution flow, поэтому "уметь" async он не должен.
Вполне достаточно WhenAll, который умеет await.
16 авг 18, 19:58    [21644976]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2421
hVostt
Вполне достаточно WhenAll, который умеет await.

Ну а если элементов сотни, глупо же выполнять их на сотне потоков... Разумно приделать какое-то "горло". По второй ссылке из первого поста ТСа весьма привлекательным выглядит самое последнее решение, где горлышко организовано с помощью SemaphoreSlim
+ ForEachAsyncConcurrent
An extension method for this which makes use of SemaphoreSlim and also allows to set maximum degree of parallelism
    /// <summary>
    /// Concurrently Executes async actions for each item of <see cref="IEnumerable<typeparamref name="T"/>
    /// </summary>
    /// <typeparam name="T">Type of IEnumerable</typeparam>
    /// <param name="enumerable">instance of <see cref="IEnumerable<typeparamref name="T"/>"/></param>
    /// <param name="action">an async <see cref="Action" /> to execute</param>
    /// <param name="maxDegreeOfParallelism">Optional, An integer that represents the maximum degree of parallelism,
    /// Must be grater than 0</param>
    /// <returns>A Task representing an async operation</returns>
    /// <exception cref="ArgumentOutOfRangeException">If the maxActionsToRunInParallel is less than 1</exception>
    public static async Task ForEachAsyncConcurrent<T>(
        this IEnumerable<T> enumerable,
        Func<T, Task> action,
        int? maxDegreeOfParallelism = null)
    {
        if (maxDegreeOfParallelism.HasValue)
        {
            using (var semaphoreSlim = new SemaphoreSlim(
                maxDegreeOfParallelism.Value, maxDegreeOfParallelism.Value))
            {
                var tasksWithThrottler = new List<Task>();

                foreach (var item in enumerable)
                {
                    // Increment the number of currently running tasks and wait if they are more than limit.
                    await semaphoreSlim.WaitAsync();

                    tasksWithThrottler.Add(Task.Run(async () =>
                    {
                        await action(item);

                        // action is completed, so decrement the number of currently running tasks
                        semaphoreSlim.Release();
                    }));
                }

                // Wait for all tasks to complete.
                await Task.WhenAll(tasksWithThrottler.ToArray());
            }
        }
        else
        {
            await Task.WhenAll(enumerable.Select(item => action(item)));
        }
    }

Sample Usage:
await enumerable.ForEachAsyncConcurrent(
    async item =>
    {
        await SomeAsyncMethod(item);
    },
    5);
16 авг 18, 22:13    [21645091]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
hVostt
Member

Откуда:
Сообщений: 16313
LR,

Оставлю это здесь

https://docs.microsoft.com/ru-ru/dotnet/standard/asynchronous-programming-patterns/consuming-the-task-based-asynchronous-pattern
16 авг 18, 22:39    [21645116]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
hVostt
Member

Откуда:
Сообщений: 16313
LR
Ну а если элементов сотни, глупо же выполнять их на сотне потоков...


https://docs.microsoft.com/ru-ru/dotnet/standard/asynchronous-programming-patterns/consuming-the-task-based-asynchronous-pattern#throttling
16 авг 18, 22:41    [21645122]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2421
hVostt
https://docs.microsoft.com/ru-ru/dotnet/standard/asynchronous-programming-patterns/consuming-the-task-based-asynchronous-pattern#throttling

Ага, получается в документации эти вопросы рассмотрены, но кто ж ее читает)) И еще, если посмотреть в Task.WhenAny, с созданием копии списка задач, то вариант с семафором может получиться и побыстрее, х.з.
16 авг 18, 23:05    [21645139]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
LR
Ну а если элементов сотни, глупо же выполнять их на сотне потоков...

С чего их сотня если пул потоков по умолчанию настройка макс около 20 потоков.
Остальные ждать будут.
И писать ничего не надо.
16 авг 18, 23:24    [21645168]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2421
Petro123
LR
Ну а если элементов сотни, глупо же выполнять их на сотне потоков...

С чего их сотня если пул потоков по умолчанию настройка макс около 20 потоков.
Остальные ждать будут.
И писать ничего не надо.

Ну какая разница, суть в другом - забирать все потоки из пула для одной задачи, если только она не единственная - глупо.
16 авг 18, 23:31    [21645178]     Ответить | Цитировать Сообщить модератору
 Re: Как делать кучу параллельных IO-Bound операций ?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
LR
Ну какая разница, суть в другом - забирать все потоки из пула для одной задачи, если только она не единственная - глупо.

суть нелогична.
Если задача одна - зачем параллелить?
Об чём топик?
Как хранимку распарралелить "чтобы было"?
16 авг 18, 23:39    [21645185]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / WinForms, .Net Framework Ответить