Parallel processing 在由CPU和I/O绑定操作组成的循环体中,如何确定并行度?

Parallel processing 在由CPU和I/O绑定操作组成的循环体中,如何确定并行度?,parallel-processing,async-await,Parallel Processing,Async Await,我正在使用一个ForEachAsync循环,如在的博客文章中所述 我的循环体执行I/O(异步/等待)和CPU绑定操作的组合。在这种情况下,决定并行度需要考虑哪些因素 public static Task ForEachAsync<T>( this IEnumerable<T> source, int degreeOfParallelism, Func<T, Task> body) { if (degreeOfParallelis

我正在使用一个ForEachAsync循环,如在的博客文章中所述

我的循环体执行I/O(异步/等待)和CPU绑定操作的组合。在这种情况下,决定并行度需要考虑哪些因素

public static Task ForEachAsync<T>(
    this IEnumerable<T> source,
    int degreeOfParallelism,
    Func<T, Task> body)
{
    if (degreeOfParallelism <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(degreeOfParallelism));
    }

    return Task.WhenAll(
        from partition in Partitioner
                          .Create(source)
                          .GetPartitions(degreeOfParallelism)
        select Task.Run(async () =>
        {
            using (partition)
            {
                while (partition.MoveNext())
                {
                    await body(partition.Current);
                }
            }
        }));
}

public async Task ProcessChangesAsync(
    IChangeFeedObserverContext context,
    IReadOnlyList<Document> docs,
    CancellationToken cancellationToken)
{
    // This function receives list of documents that need to be processed in parallel
    await docs.ForEachAsync(8, async doc =>
    {
        await ProcessDocument(doc);
    });
}

public async Task ProcessDocument(Document doc)
{
    // We get other details for this entity from database.
    var dbResult = await repository.GetDetailsFromDB(doc);

    // Get some more data from external services
    var moreDetails = await httpClient.GetMoreDataFromOtherServices(dbResult);

    // The data fetched above consists of list of elements and we iterate over the list and run business logic.
    // Use data mappers to convert the data back to entities. These are all CPU bound operations

    // Then finally we persist details in DB
    await repository.WriteToDB(...);
}
公共静态任务ForEachAsync(
这是一个数不清的来源,
int度平行性,
(职能机构)
{
if(平行度)
{
使用(分区)
{
while(partition.MoveNext())
{
等待体(partition.Current);
}
}
}));
}
公共异步任务进程ChangesAsync(
IChangeFeedObserverContext上下文,
IReadOnlyList文档,
取消令牌(取消令牌)
{
//此函数接收需要并行处理的文档列表
wait docs.ForEachAsync(8,async doc=>
{
等待处理文件(doc);
});
}
公共异步任务流程文档(文档文档)
{
//我们从数据库中获取该实体的其他详细信息。
var dbResult=await repository.GetDetailsFromDB(doc);
//从外部服务获取更多数据
var moreDetails=wait httpClient.getmoredatafromtherservices(dbResult);
//上面获取的数据由元素列表组成,我们迭代该列表并运行业务逻辑。
//使用数据映射器将数据转换回实体。这些都是CPU限制的操作
//最后,我们将细节持久化到数据库中
wait repository.WriteToDB(…);
}

除非您想限制正在运行的任务的数量,否则为什么不让系统和工作本身按照它们的方式工作呢

public static Task ForEachAsync<T>(this IEnumerable<T> source, Func<T, Task> body)
    => Task.WhenAll(from item in source select body(item));
公共静态任务ForEachAsync(此IEnumerable源代码,Func正文)
=>Task.WhenAll(来自源选择体(项)中的项);

这是一篇将近7年的文章。也许现在有更好的模式。你能显示你的代码吗?@PauloMorgado更新了代码。我想限制任务的数量,因为我们有许多任务作为服务的一部分运行。我想了解,当我们将并行性应用于异步调用时,是否需要遵循任何指导原则。为什么要限制正在运行的任务数量以及基于什么标准?因为我的循环中有CPU限制的计算。我想避免过度并行。但是你也有IO,任务调度器最终会限制CPU绑定任务的执行。在不确定CPU是否被限制的情况下限制IO听起来是正确的。