gpt4 book ai didi

.net - Parallel.Foreach 产生太多线程

转载 作者:行者123 更新时间:2023-12-03 23:16:03 26 4
gpt4 key购买 nike

问题

尽管我将在此处讨论的代码是用 F# 编写的,但它基于 .NET 4 框架,并不特别依赖于 F# 的任何特殊性(至少看起来如此!)。

我的磁盘上有一些数据,我应该从网络更新,将最新版本保存到磁盘:

type MyData =
{ field1 : int;
field2 : float }

type MyDataGroup =
{ Data : MyData[];
Id : int }

// load : int -> MyDataGroup
let load dataId =
let data = ... // reads from disk
{ Data = data;
Id = dataId }

// update : MyDataGroup -> MyDataGroup
let update dg =
let newData = ... // reads from the network and process
// newData : MyData[]

{ dg with Data = dg.Data
|> Seq.ofArray
|> Seq.append newData
|> processDataSomehow
|> Seq.toArray }

// save : MyDataGroup -> unit
let save dg = ... // writes to the disk

let loadAndSaveAndUpdate = load >> update >> save

问题是要 loadAndSaveAndUpdate我所有的数据,我将不得不多次执行该功能:
{1 .. 5000} |> loadAndSaveAndUpdate

每一步都会做
  • 一些磁盘 IO,
  • 一些数据处理,
  • 一些网络 IO(可能有很多延迟),
  • 更多数据处理,
  • 和一些磁盘 IO。

  • 在某种程度上并行完成这件事不是很好吗?不幸的是,我的阅读和解析功能都不是“异步工作流就绪”的。

    我想出的第一个(不是很好)解决方案

    任务

    我做的第一件事是设置一个 Task[]并启动它们:
    let createTask id = new Task(fun _ -> loadAndUpdateAndSave id)
    let tasks = {1 .. 5000}
    |> Seq.map createTask
    |> Seq.toArray

    tasks |> Array.iter (fun x -> x.Start())
    Task.WaitAll(tasks)

    然后我按 CTRL+ESC 只是为了查看它使用了多少线程。 15, 17, ..., 35, ..., 170, ... 直到杀死应用程序!出了点问题。

    平行线

    我做了几乎同样的事情,但使用 Parallel.ForEach(...)结果是一样的:很多很多很多线程。

    一个有效的解决方案......有点

    然后我决定只开始 n线程, Task.WaitAll(of them) ,然后是其他 n , 直到没有更多任务可用。

    这是有效的,但问题是当它完成处理时,比如 n-1任务,它将等待,等待,等待由于大量网络延迟而坚持阻塞的该死的最后一个任务。这是不好的!

    所以, 您将如何解决这个问题 ?我很乐意查看不同的解决方案,包括异步工作流(以及在这种情况下如何调整我的非异步功能)、并行扩展、奇怪的并行模式等。

    谢谢。

    最佳答案

    ParallelOptions.MaxDegreeOfParallelism限制并行方法调用运行的并发操作数

    关于.net - Parallel.Foreach 产生太多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2002864/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com