PARALLEL.RU

Дискуссионный клуб по параллельным вычислениям
Текущее время: 20 июн 18 6:40

Часовой пояс: UTC + 4 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 3 ] 
Автор Сообщение
СообщениеДобавлено: 8 сен 10 14:32 
Не в сети

Зарегистрирован: 8 сен 10 14:00
Сообщения: 3
Откуда: Казань
Здравствуйте!
Я работаю на кластере HP BLc3000 Twr CTO Enclosure (http://wwwnew.ispras.ru/ru/unicluster/technologies.php).
Программирую на C#. Поэтому распараллеливал программу с помощью MPI.NET, привязанного к Open MPI. Т.е. при выполнении программы используется Open MPI.
Я проводил эксперименты: вычислял среднее арифметическое соседей для элементов массива (операция сглаживания изображения).
Данный эксперимент я выполнял в двух вариантах:
1) Использовал 4 ядра одного узла (общая память)
2) Использовал по одному ядру процессора с каждого из 4-ех узлов (распределенная память)
Для уменьшения влияния кэша доступ к элементам массива производил в случайном порядке, объем исходных данных составлял 36 Мбайт (не умещается в кэш-память размером 12 Мбайт на процессор).
При этом "чистое" время операции без времени на пересылку в двух вариантах отличалось незначительно:
1 вариант: 42689, 17937, 12497, 7788 мс на одном, двух, трех и четырех ядрах одного узла соотвественно
2 вариант: 42365, 17497, 10880, 7398 мс на одном, двух, трех и четырех узлах соотвественно

2 вопроса: Почему такая небольшая разница при использовании различных архитектур? Ведь доступ к общей памяти теоретически должен значительно замедлять быстродействие.
И почему ускорение алгоритма растет заметно быстрее, чем количество использумых ядер? Экспериментально убедился, что при последовательном (не случайном) обходе элементов массива ускорение растет практически прямо пропорционально числу ядер.

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

public MPIPicture Smooth(MPISmoothingData data)
{
//array of bitmaps, each bitmap is in byte[]
byte[][] bitmaps = data.Bitmaps;
int dimension = bitmaps.GetLength(0);
byte[][] smoothedBitmaps = new byte[dimension][];
int arrayLenght = bitmaps[0].GetLength(0);

for (int i = 0; i < dimension; i++)
smoothedBitmaps[i] = new byte[arrayLenght];

int x, y, x1, y1, x2, y2;
Random rnd = new Random();
for (int index = 0; index < arrayLenght; index++)
{
//(x,y) is thesmoothing center
//(x1,y1) is the upper-left corner of the smoothing square
//(x2,y2) is the bottom-right corner of the smoothing square
int randomIndex = rnd.Next(arrayLenght);
x = randomIndex % data.BitmapWidth;
y = (int)(randomIndex / data.BitmapWidth + 0.5);
x1 = Math.Max(0, x - data.SmoothRadius);
y1 = Math.Max(0, y - data.SmoothRadius);
x2 = Math.Min(data.BitmapWidth - 1, x + data.SmoothRadius);
y2 = Math.Min(data.BitmapHeight - 1, y + data.SmoothRadius);

for (int d = 0; d < dimension; d++)
{
double smoothValue = 0;
int smoothSize = 0;

for (int i = x1; i <= x2; i++)
for (int j = y1; j <= y2; j++)
{
smoothValue += bitmaps[d][j * data.BitmapWidth + i];
smoothSize++;
}
smoothValue /= smoothSize;
smoothedBitmaps[d][randomIndex] = (byte)smoothValue;
}
}
MPIPicture smoothedPicture = new MPIPicture(smoothedBitmaps, data.BitmapWidth, data.BitmapHeight);
return smoothedPicture;
}

Заранее спасибо!


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 ноя 10 19:20 
Не в сети

Зарегистрирован: 8 сен 10 14:00
Сообщения: 3
Откуда: Казань
Нашел ответы на эти 2 вопроса (большое спасибо Serg_Zhum :D )

>> 1. Почему такая небольшая разница при использовании различных архитектур? Ведь доступ к общей памяти теоретически должен значительно замедлять быстродействие.

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

>> 2. И почему ускорение алгоритма растет заметно быстрее, чем количество использумых ядер?

При случайном доступе кэш-память используется очень неэффективно. Видимо, при увеличении числа ядер (и соотвественно, общего объема кэш-памяти) все большая часть данных оказывается в кэше. Таким образом, количество кэш-промахов уменьшается быстрее, чем увеличивается число ядер.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 ноя 10 20:58 
Не в сети

Зарегистрирован: 8 сен 10 14:00
Сообщения: 3
Откуда: Казань
Но возникли еще вопросы:

Сравниваю сглаживание на архитектуре с общей памятью (используя 8 ядер одного узла кластера), распраллеленное с помощью MPI и с помощью потоков. Непонятно следующее:
Если объем исходных данных программы умещается в кэш, то "чистое" время выполнения алгоритма (без учета времени на распараллеливание, загрузку и подготовку данных и т.п.) меньше при использовании потоков. А если больше объема кэша, то "чистое" время меньше для MPI.
Предположил, что MPI может быть лучше потоков за счет ложного разделения кэш-памяти при потоках, так как если не изменять общий массив из различных потоков, то результаты такие же, как и для MPI. Попробовал каждому потоку передавать свой массив для записи результатов алгоритма: при количестве потоков ThreadsCount создавал массив из ThreadsCount*2 массивов, в каждый четный записывались результаты алгоритма, а каждый нечетный массив размером 64 байт использовался для "разведения" потоков в различные кэш-линии. Но при этом "чистое" время для потоков не изменилось. Не могу понять причину...
Тому, что "чистое" время для потоков лучше "чистого" времени для MPI при малом объеме данных, вообще не могу дать объяснения.

Был бы благодарен, если бы помогли разобраться!


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 3 ] 

Часовой пояс: UTC + 4 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB