2010-05-28 2 views
2

Меня очень интересует использование недавно расширенных функций параллелизма в .NET 4.0.Как можно полностью использовать недавно расширенные функции параллелизма в .NET 4.0?

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

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

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

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

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

Спасибо! =)

ответ

4

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

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

Я бы рекомендовал вам ознакомиться с Parallel Programming in the .NET Framework в качестве хорошего отправного места.

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

Я лично нашел классы задач и задач {T} в параллельной библиотеке задач более гибкими при создании и координации асинхронной работы.

+0

Существует несколько примеров в блоге групп http://blogs.msdn.com/pfxteam, также имеется тонна образцов, доступных по адресу http://code.msdn.microsoft.com/ParExtSamples. – Rick

2

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

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

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

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

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

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

Update ...

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

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

Sequential:

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 может быть лучше, в некоторых случаях это в значительной степени зависит от предпочтений программиста.

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

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; 
} 

Это позволяет создавать графики задач, где выход одной задачи, подаваемые в другой (Task Graph или график фьючерсов):

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); 
} 

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

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); 
} 

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

+0

Спасибо за подсказку. =) Кроме того, можете ли вы опубликовать простой пример кода, чтобы показать адрес другим способом, чем PLINQ? Благодаря!=) –

+0

Воля, я обновил свой ответ намного подробнее. Просто так ваш пример лучше всего подходит для PLinq. –

+0

Благодарим вас за это обновление. Мой пример подходит для PLINQ, поскольку это то, что привлекло мое внимание больше всего, и это также самый распространенный пример, объясняющий возможность параллелизма. Ваши примеры великолепны! Я уже поддержал, но я хотел бы снова поддержать ваш ответ. И стыдно, что я не могу принять два ответа в качестве решения моего вопроса. Кроме того, я изучу ваши примеры, чтобы познакомиться с параллелизмом в .NET 4.0. Я также загружу образец вашей книги и посмотрю, может ли это быть хорошей ссылкой для меня. Спасибо Аде! –