Я закодировал очень простую программу "Word Count", которая читает файл и подсчитывает каждое вхождение слова в файл. Вот часть кода:
class Alaki
{
private static List<string> input = new List<string>();
private static void exec(int threadcount)
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = threadcount;
Parallel.ForEach(Partitioner.Create(0, input.Count),options, (range) =>
{
var dic = new Dictionary<string, List<int>>();
for (int i = range.Item1; i < range.Item2; i++)
{
//make some delay!
//for (int x = 0; x < 400000; x++) ;
var tokens = input[i].Split();
foreach (var token in tokens)
{
if (!dic.ContainsKey(token))
dic[token] = new List<int>();
dic[token].Add(1);
}
}
});
}
public static void Main(String[] args)
{
StreamReader reader=new StreamReader((@"c:\txt-set\agg.txt"));
while(true)
{
var line=reader.ReadLine();
if(line==null)
break;
input.Add(line);
}
DateTime t0 = DateTime.Now;
exec(Environment.ProcessorCount);
Console.WriteLine("Parallel: " + (DateTime.Now - t0));
t0 = DateTime.Now;
exec(1);
Console.WriteLine("Serial: " + (DateTime.Now - t0));
}
}
Это просто и прямо. Я использую словарь для подсчета каждого слова. Стиль примерно основан на модели программирования MapReduce. Как вы можете видеть, каждая задача использует собственный частный словарь. Таким образом, нет общих переменных; просто куча задач, которые подсчитывают слова сами по себе. Вот результат, когда код запускается на четырехъядерном процессоре i7:
Параллельно: 00: 00: 01.6220927
Номер: 00: 00: 02.0471171
Ускорение составляет около 1,25, что означает трагедию! Но когда я добавляю некоторую задержку при обработке каждой строки, я могу достичь значений ускорения около 4.
В исходном параллельном исполнении без задержки загрузка процессора едва достигает 30%, и поэтому ускорение не является многообещающим. Но, когда мы добавляем некоторую задержку, загрузка процессора достигает 97%.
Во-первых, я думал, что причиной является связанный с IO характер программы (но я думаю, что вставка в словарь в какой-то степени требует интенсивного процессора), и это кажется логичным, потому что все потоки считывают данные с шины общей памяти, Однако удивительным моментом является то, что одновременно я запускаю 4 экземпляра последовательных программ (без задержек), загрузка процессора достигает примерно рейзов, а все четыре экземпляра заканчиваются примерно через 2,3 секунды!
Это означает, что, когда код запускается в конфигурации многопроцессорности, он достигает значения ускорения около 3,5, но когда он запускается в конфигурации с несколькими потоками, ускорение составляет около 1,25.
Что вы думаете? Что-то не так в моем коде? Потому что я думаю, что нет общих данных вообще, и я думаю, что код не будет испытывать никаких утверждений. Есть ли недостаток во время выполнения .NET?
Спасибо заранее.