Funzionamento in parallelo di dosaggio
-
26-09-2019 - |
Domanda
C'è il supporto integrato in TPL (Task-Parallel-Library) per le operazioni di dosaggio?
Recentemente sono stato a giocare con una routine per effettuare la sostituzione dei caratteri su un array di caratteri utilizzando una tabella di ricerca vale a dire traslitterazione:
for (int i = 0; i < chars.Length; i++)
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
}
ho potuto vedere che questo potrebbe essere banalmente parallelizzati, così saltato con un primo tentativo che sapevo effettuerebbe peggio, come i compiti sono stati troppo a grana fine:
Parallel.For(0, chars.Length, i =>
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
});
Ho poi rielaborato l'algoritmo per uso dosaggio in modo che il lavoro potrebbe essere chunked su diversi thread in meno lotti a grana fine. Questo uso di fili come previsto e ho avuto un po 'vicino alla velocità lineare fino.
Sono sicuro che ci deve essere costruito il supporto integrato per il dosaggio nel TPL. Qual è la sintassi, e come si usa?
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;
}
}
});
Aggiorna
Dopo aver usato @ risposta di Oliver e la sua sostituzione con un Parallel.For
Parallel.ForEach e partizionamento il codice è il seguente:
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;
}
}
});
Soluzione
Per una migliore ottenere la vostra testa intorno si dovrebbe ottenere il modelli per la programmazione parallela: comprensione e l'applicazione Patterns parallelo con il .NET Framework 4 . E 'una grande fonte e spiega i modi comuni su come utilizzare il TPL.
Date un'occhiata a pagina 26 (molto piccoli corpi di loop). Ci troverete questo esempio:
Parallel.ForEach(Partitioner.Create(from, to), range =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
// ... process i
}
});
Così il pezzo mancante si sta cercando è la System.Concurrent.Collections.Partitioner
.