2011-01-06 5 views
6

Есть ли встроенная поддержка в TPL (Task-Parallel-Library) для операций дозирования?Parallel Operation Batching

Я недавно играл с обычной для выполнения замены символов на массив символов с помощью таблицы поиска, т.е. транслитерации:

for (int i = 0; i < chars.Length; i++) 
{ 
    char replaceChar; 

    if (lookup.TryGetValue(chars[i], out replaceChar)) 
    { 
     chars[i] = replaceChar; 
    } 
} 

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

Parallel.For(0, chars.Length, i => 
{ 
    char replaceChar; 

    if (lookup.TryGetValue(chars[i], out replaceChar)) 
    { 
     chars[i] = replaceChar; 
    } 
}); 

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

Я уверен, что в TPL должна быть встроенная поддержка для дозирования. Каков синтаксис и как его использовать?

const int CharBatch = 100; 
int charLen = chars.Length; 

Parallel.For(0, ((charLen/CharBatch) + 1), i => 
{ 
    int batchUpper = ((i + 1) * CharBatch); 

    for (int j = i * CharBatch; j < batchUpper && j < charLen; j++) 
    { 
     char replaceChar; 

     if (lookup.TryGetValue(chars[j], out replaceChar)) 
     { 
      chars[j] = replaceChar; 
     } 
    } 
}); 

Update

После использования @ ответ Оливера и замена Parallel.For с Parallel.ForEach and a Partitioner код выглядит следующим образом:

const int CharBatch = 100; 

Parallel.ForEach(Partitioner.Create(0, chars.Length, CharBatch), range => 
{ 
    for (int i = range.Item1; i < range.Item2; i++) 
    { 
     char replaceChar; 

     if (lookup.TryGetValue(chars[i], out replaceChar)) 
     { 
      chars[i] = replaceChar; 
     } 
    } 
}); 

ответ

15

Для лучшего получения вокруг головы, вы должны получить Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4. Это отличный источник и объясняет общие способы использования TPL.

Взгляните на страницу 26 (Очень маленькие корпуса петли). Там вы найдете пример:

Parallel.ForEach(Partitioner.Create(from, to), range => 
{ 
    for (int i = range.Item1; i < range.Item2; i++) 
    { 
     // ... process i 
    } 
}); 

Так недостающий кусок вы ищете является System.Concurrent.Collections.Partitioner.

+0

Спасибо за ссылку, но у вас есть конкретный ответ на мой вопрос? –

+0

@chibacity: просто обновил ответ. – Oliver

+0

Это замечательное спасибо. Работает отлично и очень хороший API тоже :) Я обновил свой вопрос на примере, основанном на вашем ответе. –