【问题标题】:Parallel Invoke is taking too long to launchParallel Invoke 启动时间过长
【发布时间】:2023-03-16 14:04:01
【问题描述】:

我需要一些建议。我有一个应用程序可以处理来自证券交易所的实时数据馈送的交易信息。我的处理落后了。

由于我运行在具有 32 GB 主内存的 3GHz Intel I7 上,我应该有足够的能力来执行此应用程序。 Parse 例程将交易信息存储在 SQL Server 2014 数据库中,该数据库在 Windows 2012 R2 服务器上运行。

我在主处理循环中放了如下时序信息:

  invokeTime.Restart();

  Parallel.Invoke(() => parserObj.Parse(julian, data));

  invokeTime.Stop();
  var milliseconds = invokeTime.ElapsedMilliseconds;
  if (milliseconds > maxMilliseconds) {
    maxMilliseconds = milliseconds;
    messageBar.SetText("Invoke: " + milliseconds);
  }

我用了 1122 毫秒来执行 Parallel.Invoke。类似的计时测试表明 Parse 例程只需要 7 毫秒(最大值)。

除了执行 Parallel.Invoke 之外,还有更好的数据处理方式吗?

任何建议将不胜感激。

查尔斯

【问题讨论】:

  • 你为什么打电话给Parallel.Invoke,只有一个代表?
  • 这可能对你有用:stackoverflow.com/q/10802333/2638872 看起来其他人也想知道同样的事情。
  • 信息不足,只能猜测。这些线程中有多少是同时运行的?如果没有等待的线程,操作系统需要时间来启动一个新的池线程。您可以查看ThreadPool.SetMinThreads。此外,如果您运行的线程过多,一切都会变慢。
  • 发布的代码没有并行执行任何操作。使用 Task.Start() 或 Threadpool.QueueUserWorkitem()。

标签: c# multithreading c#-4.0


【解决方案1】:

你试过了吗

Task.Factory.StartNew(() => {
 parserObj.Parse(julian, data));
});

您的 Parse 方法看起来如何?也许瓶颈就在那里......

【讨论】:

  • 如果你这样做,那么你实际上是在计时什么都不做,因为你永远不会等待操作完成。这里仍然没有并行化,因为只有一个工作单元要完成。
  • 这是一个需要澄清的问题,所以应该是评论而不是答案。
  • @Servy - 时间测量一文不值,但核心业务可能会获利很多。
  • @HenkHolterman 当只有一个工作单元要完成时,在一个新线程中运行它,然后在原始线程中什么都不做,什么也得不到。现在,如果我们真的知道更多关于这里实际所做的事情的详细信息,那么对于是否或可能如何并行化它可能会得到一个明智的答案。
【解决方案2】:

在 Stephen Toub 的文章:http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx 中,他描述:“Task.Run 可以而且应该用于最常见的情况,即简单地卸载一些要在 ThreadPool 上处理的工作”。这正是我想要做的,将 Parse rosutine 卸载到后台线程。所以我改变了:

Parallel.Invoke(() => parserObj.Parse(julian, data));

到:

Task.Run(() => parserObj.Parse(julian, data));

我还通过以下方式将 ThreadPool 中的线程数从 8 个增加到 80 个:

    int minWorker, minIOC;;
    ThreadPool.GetMinThreads(out minWorker, out minIOC);
    var newMinWorker = 10*minWorker;
    var newMinIOC = 10*minIOC;
    if (ThreadPool.SetMinThreads(newMinWorker, newMinIOC)) {
      textBox.AddLine("The minimum no. of worker threads is now: " + newMinWorker);
    } else {
      textBox.AddLine("Drat! The minimum no. of worker threads could not be changed.");
    }

每天运行 6 1/2 小时的解析循环如下所示:

    var stopWatch = new Stopwatch();
    var maxMilliseconds = 0L;
    while ((data = GetDataFromIQClient()) != null) {
      if ( MarketHours.IsMarketClosedPlus2() ) {
        break;
      }
      stopWatch.Restart();

      Task.Run(() => parserObj.Parse(julian, data));

      stopWatch.Stop();
      var milliseconds = stopWatch.ElapsedMilliseconds;
      if (milliseconds > maxMilliseconds) {
        maxMilliseconds = milliseconds;
        messageBar.SetText("Task.Run: " + milliseconds);
      }
    }

现在,调用 Task.Run 花费的最长时间为 96 毫秒,解析器花费的最长时间为 18 毫秒。我现在正在跟上数据传输。

查尔斯

【讨论】:

    猜你喜欢
    • 2023-04-06
    • 1970-01-01
    • 2019-12-23
    • 2016-05-01
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多