Библиотека OpenMP

Здравствуйте.

На днях хотел разобраться с директивой $omp для распараллеливания расчётов.

Скажите, пожалуйста, почему в случае перемножения элементов пары векторов параллельный расчёт оказывается в несколько раз медленнее последовательного (см. скриншот) ?

Я плохо понимаю Milliseconds, а описания языка нет, но, насколько я понял, вы считаете время вместе с созданием массивов, которое занимает лишнее время.

Это укороченный пример из папки Samples на перемножение матриц. Только там квадратные матрицы NxN, а у меня вектора, ничего больше я не менял. Матрицы перемножаются в параллельных потоках быстрее, а вот вектора почему-то наоборот

@Ulysses абсолютно прав, в приведенном примере первый вызов Milliseconds происходит после создания массивов и выполнения параллельной версии алгоритма – вот оно это всё и считает, а второй вызов корректен, считает только время работы последовательной версии. Подправьте программу так:

  var a := Arrays.CreateRandomRealMatrix(1,n);
  var b := Arrays.CreateRandomRealMatrix(1,n);
  var c := new real[1,n];
  var d := Milliseconds;
  ParallelMult(a,b,c,n);
  writeln('Параллельное перемножение матриц: ',Milliseconds-d,' миллисекунд');
  d := Milliseconds;
  Mult(a,b,c,n);
  writeln('Последовательное перемножение матриц: ',Milliseconds-d,' миллисекунд');

Если всё очень сильно утрировать, то получается такое пояснение: В Samples пример неправильный, но для матриц это несущественно. Дело в том, что затраты на создание случайной матрицы составят O(n2) – пропорционально количеству элементов, то есть для n=400 это 4002 некоторых простых действий (создать/присвоить). Перемножение матриц потребует O(n3) действий, то есть 4003. Вот и считаем: в первом случае создаем две матрицы и перемножаем параллельно (пусть с ускорением в полтора раза – для двухъядерных процессоров сгодится), получаем: 2*4002+4003/1.5 = 4.28Е7. А последовательный алгоритм только перемножает, 4003 = 6.4Е7, то есть дольше. Разница может варьироваться в зависимости от кучи факторов, но параллельный + создание матриц всё равно быстрее последовательного.

Когда Вы перемножаете вектора, по сути, то и создание случайного вектора, и перемножение имеют сложность O(n). То есть в первом случае создаются два вектора и перемножаются – 2*400+400/1.5, а второе измерение – просто перемножение стоимостью 400. Сколько бы у вас не было ядер/потоков, тут обычное умножение всё равно быстрее создания двух векторов, и выигрыша не получите.

1 лайк