Как найти горячие точки для параллелизма в .net 4? - PullRequest
2 голосов
/ 17 ноября 2010

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

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

int[] data = new int[1000000];    // Just a big trunk of data.

// Here is just a procedure on the trunk of data, performing repeated work.
void SequentialProcedure(){
    for(int  i = 0; i < data.Length; i++) data[i] += rand.Next();
}

Для такого парня, как я, без особого опыта параллелизма, на первый взгляд, это выглядело бы как функция, которую можно применить с каким-нибудь изумительным навыком параллелизма:

int[] data = new int[1000000];    // The same big trunk of data.

// A parallel implementation.
void ParallelProcedure(){
    Parallel.ForEach(Partitioner.Create(0, data.Length),
        range => {
            for(int i = range.Item1; i < range.Item2; i++) data[i] += rand.Next();
        }
    );
}

OK. Хотя я читаю что-то и знаю, что реальная задача добавления случайного числа к каждому элементу вектора мала по сравнению со стоимостью создания делегатов и использования диапазонов, чтобы сделать каждую параллельную задачу более мясной, параллельная версия все еще медленнее, чем последовательная версия , В этот момент я потеряюсь: значит, SequentialProcedure - это просто функция, не подходящая для параллелизма? или способ, которым я пытаюсь распараллелить это просто неправильно? есть ли какие-то предложения, указания от гуру, которым мы можем следовать при определении того, где параллелизм будет иметь больший эффект, а где параллелизм будет просто пустой тратой времени?

Большое спасибо за любую помощь.

Edit:

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

int[] data = new int[100];

void SequentialProcedure(){
    for(int i = 0; i < data.Length; i++){
        for(int j = 0; j < 500000; j++) data[i] = rand.Next(j, Int32.MaxValue);
    }
}

И параллельная версия становится:

int[] data = new int[100];
void ParallelProcedure(){
    Parallel.ForEach(Partitioner.Create(0, data.Length),
    range => {
        for(int i = range.Item1; i < range.Item2; i++){
            for(int j = 0; j < 500000; j++) data[i] = rand.Next(j, Int32.MaxValue);
        }
    }
}

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

Возможна ли проблема выделения памяти / кэширования?

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

Ответы [ 2 ]

1 голос
/ 17 ноября 2010

Я нашел место, где он замедляется.Это общий объект Random, который портит производительность.Когда я делаю рэндовую нить, я набираю скорость.Параллельная версия примерно в 4 раза быстрее, чем последовательная версия на моей четырехъядерной машине.Но все же вопрос хорошо открыт для любого проницательного предложения.

0 голосов
/ 17 ноября 2010

Профиль.Когда вы найдете что-то медленное, посмотрите, выполняет ли оно параллелизованные операцииЭто ваши «горячие точки для параллелизма».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...