Как можно в полной мере использовать недавно расширенные функции параллелизма в .NET 4.0? - PullRequest
2 голосов
/ 28 мая 2010

Я очень заинтересован в использовании новых улучшенных функций параллелизма в .NET 4.0.

Я также видел некоторые возможности его использования в F #, также как и в C #.

Несмотря на это, я могу видеть только то, что PLINQ может предложить, например, со следующим:

var query = from c in Customers.AsParallel()
            where (c.Name.Contains("customerNameLike"))
            select c;

Наверняка должно быть какое-то другое применение этой вещи параллелизма.

Есть ли у вас другие примеры его использования? Это особенно обращено к PLINQ, или есть другое простое использование как PLINQ?

Спасибо! =)

Ответы [ 3 ]

4 голосов
/ 28 мая 2010

Новые функции параллельного программирования, предоставляемые в .NET 4, не ограничиваются только PLINQ.

Как заявляет Microsoft: « Visual Studio 2010 и .NET Framework 4 расширяют поддержку параллельного программирования, предоставляя новую среду выполнения, новые типы библиотек классов и новые инструменты диагностики. Эти функции упрощают параллельную разработку, так что может писать эффективный, детальный и масштабируемый параллельный код в естественной идиоме, не работая напрямую с потоками или пулом потоков."

Я бы порекомендовал вам рассмотреть Параллельное программирование в .NET Framework в качестве хорошей отправной точки.

В целом .NET 4 и Visual Studio 2010 предоставляют следующие функции:

Лично я обнаружил, что классы Task и Task {T} в библиотеке параллельных задач более гибки при создании и координации асинхронной работы.

2 голосов
/ 06 августа 2010

Моя команда также только что закончила книгу об этом ...

Параллельное программирование с Microsoft® .NET: Шаблоны проектирования для разложения и координации на многоядерных архитектурах

Колин Кэмпбелл, Ральф Джонсон, Эд Миллер и Стивен Туб. Предисловие Тони Хей

Вы можете скачать черновик и образцы здесь: http://parallelpatterns.codeplex.com/

Полная книга будет доступна на MSDN позже в этом месяце и на Amazon в октябре.

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

Обновление ...

Чтобы ответить на ваш вопрос (ниже) на проблему, которую вы выбрали, реализация Aggregation (из списка, создающего агрегат на основе содержимого списка), оказывается, гораздо лучше отображает PLinq, чем альтернативный Parallel.ForEach. Есть пример агрегации с Parallel.ForEach на p72 в PDF.

Если вы просто хотите обновить содержимое набора с помощью PLinq, сопоставление будет намного проще. Например, следующий код перебирает список счетов, вычисляет тренд баланса и помечает счета с прогнозируемыми балансами, превышающими лимит овердрафта.

Последовательная:

static void UpdatePredictionsSequential(AccountRepository accounts)
{
    foreach (Account account in accounts.AllAccounts)
    {
        Trend trend = SampleUtilities.Fit(account.Balance);
        double prediction = trend.Predict(account.Balance.Length + NumberOfMonths); 
        account.SeqPrediction = prediction;
        account.SeqWarning = prediction < account.Overdraft;
    }
}

PLINQ:

static void UpdatePredictionsPlinq(AccountRepository accounts)
{            
    accounts.AllAccounts
        .AsParallel()
        .ForAll(account =>
            {
                Trend trend = SampleUtilities.Fit(account.Balance);
                double prediction = trend.Predict(account.Balance.Length + NumberOfMonths);
                account.PlinqPrediction = prediction;
                account.PlinqWarning = prediction < account.Overdraft;         
            });
}

Parallel.ForEach:

static void UpdatePredictionsParallel(AccountRepository accounts)
{
    Parallel.ForEach(accounts.AllAccounts, account =>
    {
        Trend trend = SampleUtilities.Fit(account.Balance);
        double prediction = trend.Predict(account.Balance.Length + NumberOfMonths);
        account.ParPrediction = prediction;
        account.ParWarning = prediction < account.Overdraft;
    });
}

В некоторых случаях PLinq может быть наиболее выразительным выбором. В других случаях Parallel.For / ForEach может быть лучше, в некоторых случаях это просто вопрос предпочтений программиста.

Однако библиотека параллельных задач поддерживает больше, чем шаблоны параллельного цикла и агрегации. Это позволяет создавать задачи, которые будут запланированы для параллельного выполнения на многоядерном оборудовании (шаблон параллелизма задач):

static int ParallelTaskImageProcessing(Bitmap source1, Bitmap source2,
                                    Bitmap layer1, Bitmap layer2, Graphics blender)
{
    Task toGray = Task.Factory.StartNew(() => SetToGray(source1, layer1));
    Task rotate = Task.Factory.StartNew(() => Rotate(source2, layer2));
    Task.WaitAll(toGray, rotate);
    Blend(layer1, layer2, blender);
    return source1.Width;
} 

Позволяет создавать графики задач, в которых выходные данные одной задачи передаются в другую (график задач или шаблон Futures):

public static int Example4()
{
    var a = 22;

    var cf = Task<int>.Factory.StartNew(() => F2(a));
    var df = cf.ContinueWith((t) => F3(t.Result));
    var b = F1(a);
    var f = F4(b, df.Result);
    return f;
}

Где F1-F4 - функции, входы и выходы которых имеют зависимости.

Поддерживается создание деревьев зависимых задач для задач «Разделяй и властвуй», таких как сортировка (шаблон параллелизма динамических задач):

static void ParallelWalk<T>(Tree<T> tree, Action<T> action)
{
    if (tree == null) return;
    var t1 = Task.Factory.StartNew(
               () => action(tree.Data));
    var t2 = Task.Factory.StartNew(
               () => ParallelWalk(tree.Left, action));
    var t3 = Task.Factory.StartNew(
               () => ParallelWalk(tree.Right, action));
    Task.WaitAll(t1, t2, t3);
}

Он также реализует несколько (потоковых) коллекций для использования в параллельной программе. Что позволяет прямую реализацию, например, шаблона Pipeline:

static void Chapter7Example01Pipeline(int seed)
{
    Console.Write("Begin Pipelined Sentence Builder");

    var buffer1 = new BlockingCollection<string>(BufferSize);
    var buffer2 = new BlockingCollection<string>(BufferSize);
    var buffer3 = new BlockingCollection<string>(BufferSize);

    var f = new TaskFactory(TaskCreationOptions.LongRunning, 
                            TaskContinuationOptions.None);

    var stage1 = f.StartNew(() => ReadStrings(buffer1, seed));
    var stage2 = f.StartNew(() => CorrectCase(buffer1, buffer2));
    var stage3 = f.StartNew(() => CreateSentences(buffer2, buffer3));
    var stage4 = f.StartNew(() => WriteSentences(buffer3));

    Task.WaitAll(stage1, stage2, stage3, stage4);
}

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

1 голос
/ 28 мая 2010

Смотреть это представление Скотта Хансельмана с 39:30 до 48:36. (Начиная с 39 минут 30 секунд разговора).

...