Параллельный Linq - Использование больше потоков, чем процессоры (для независящих от ЦП задач)

{oldActiveCode : oldTime} и {"1000812001401": 1553503004448} не совпадают. Первый устанавливает свойство oldActiveCode, а второй устанавливает свойство 1000812001401.

Если свойство должно быть 1000812001401, оно должно быть вычисляемым свойством, {[oldActiveCode] : oldTime}.

10
задан Tristan Havelick 8 April 2010 в 14:09
поделиться

4 ответа

URL относятся к тому же серверу? Если так, могло случиться так ударом предела HTTP-соединения вместо предела поточной обработки. Существует простой способ сказать - изменяют Ваш код на:

int threads = 10;
Dictionary<string, string> results = urls.AsParallel(threads)
    .ToDictionary(url => url, 
                  url => {
                      Console.WriteLine("On thread {0}",
                                        Thread.CurrentThread.ManagedThreadId);
                      return GetPage(url);
                  });

Править: Хм. Я не могу добраться ToDictionary() параллелизировать вообще с небольшим количеством примера кода. Это хорошо работает для Select(url => GetPage(url)) но нет ToDictionary. Будет искать вокруг немного.

Править: Хорошо, я все еще не могу добраться ToDictionary для параллелизации но можно работать вокруг этого. Вот короткая, но полная программа:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Linq.Parallel;

public class Test
{

    static void Main()
    {
        var urls = Enumerable.Range(0, 100).Select(i => i.ToString());

        int threads = 10;
        Dictionary<string, string> results = urls.AsParallel(threads)
            .Select(url => new { Url=url, Page=GetPage(url) })
            .ToDictionary(x => x.Url, x => x.Page);
    }

    static string GetPage(string x)
    {
        Console.WriteLine("On thread {0} getting {1}",
                          Thread.CurrentThread.ManagedThreadId, x);
        Thread.Sleep(2000);
        return x;
    }
}

Так, сколько потоков это использует? 5. Почему? Кто его знает. У меня есть 2 процессора, таким образом, это не это - и мы указали 10 потоков, таким образом, это не это. Это все еще использует 5, даже если я изменяюсь GetPage ковать ЦП.

Если только необходимо использовать это для одной конкретной задачи - и Вы не возражаете против немного вонючего кода - Вы могли бы быть лучшими от реализации его сами, чтобы быть честными.

12
ответ дан 3 December 2019 в 19:35
поделиться

По умолчанию .NET имеет предел 2 параллельных соединений к сервисному центру конца (IP:port). Вот почему Вы не видели бы различия, если все URL к одному и тому же серверу.

Этим можно управлять с помощью ServicePointManager. Свойство DefaultPersistentConnectionLimit.

7
ответ дан 3 December 2019 в 19:35
поделиться

Контролируйте свой сетевой трафик. Если URL от того же домена, он может ограничивать пропускную способность. Больше соединений не могло бы на самом деле обеспечить ускорение.

0
ответ дан 3 December 2019 в 19:35
поделиться

Я думаю, что уже существуют хорошие ответы на вопрос, но я хотел бы высказать одно важное мнение. Используя PLINQ для задач, которые не являются зависящими от ЦП, в принципе неправильный дизайн. Чтобы не сказать, что это не будет работать - это будет, но использующий несколько потоков, когда это будет ненужным, может доставить неприятности.

Unfortunatelly, нет никакого хорошего способа решить эту проблему в C#. В F# Вы могли использовать асинхронные рабочие процессы, которые работают параллельно, но не блокируют поток при выполнении асинхронных вызовов (под покрытием, это использует BeginOperation и EndOperation методы). Можно найти больше информации здесь:

Та же идея может в некоторой степени использоваться в C#, но это выглядит немного странным (но это более эффективно). Я написал статью об этом и существует также библиотека, которая должна быть немного более развита, чем моя исходная идея:

1
ответ дан 3 December 2019 в 19:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: