Nano Hash - криптовалюты, майнинг, программирование

Параллельное выполнение с использованием OpenMP занимает больше времени, чем последовательное выполнение c ++, правильно ли я рассчитываю время выполнения?

Без использования директив Open MP - последовательное выполнение - см. снимок экрана здесь

Использование директив OpenMp - параллельное выполнение - см. снимок экрана здесь

#include "stdafx.h"
#include <omp.h>
#include <iostream>
#include <time.h>
using namespace std;

static long num_steps = 100000;
double step;
double pi;

int main()
{
clock_t tStart = clock();
int i;
double x, sum = 0.0;
step = 1.0 / (double)num_steps;

#pragma omp parallel for shared(sum)
for (i = 0; i < num_steps; i++)
{
    x = (i + 0.5)*step;
#pragma omp critical
    {
        sum += 4.0 / (1.0 + x * x);
    }
}

pi = step * sum;
cout << pi <<"\n";
printf("Time taken: %.5fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
getchar();
return 0;
}

Я пробовал несколько раз, последовательное выполнение всегда быстрее, почему?

Время последовательного выполнения: 0,0200 с. Время параллельного выполнения: 0,02500 с.

почему здесь последовательное выполнение быстрее? правильно ли я рассчитываю время выполнения?


  • Помните, что для создания потоков требуется время, и ваш алгоритм не займет так много времени. 20.04.2018
  • о, это так, спасибо! 20.04.2018
  • Многие вещи могут привести к тому, что параллельное выполнение будет медленнее, чем непараллельное. Например: накладные расходы на раскручивание потоков перевешивают работу, выполняемую в каждом потоке. Стоимость синхронизации перевешивает преимущества параллельной работы. Ложное совместное использование (из-за плохой / неосведомленной реализации) убивает производительность многопоточной версии. И многое, многое другое. Многопоточность - это сложно, не панацея. 20.04.2018
  • Обратите внимание! Спасибо за разъяснения. 20.04.2018
  • Чтобы ответить на ваш вопрос: нет, вы неправильно рассчитываете время выполнения. См. stackoverflow.com/questions/13351396/ и ряда других причин, почему не использовать clock для синхронизации параллельных программ. 20.04.2018
  • Возможный дубликат OpenMP time и clock () вычисляют два разных результата 21.04.2018
  • @Zulan, clock() вряд ли проблема, потому что OP использует stdafx.h, который является предварительно скомпилированным заголовком из Visual Studio и clock() не имеет этой проблемы со средой выполнения MSVC. Эта проблема возникает только в вариантах библиотеки C. 21.04.2018
  • @Zboson практически ты прав. Однако, если вы сосредоточитесь на правильно ли я вычисляю время выполнения?, я думаю, что дублирование оправдано. 21.04.2018
  • Избавьтесь от критической прагмы и замените shared(sum) на reduction(+:sum) private(x) 22.04.2018

Ответы:


1

OpenMP внутренне реализует многопоточность для параллельной обработки, и производительность многопоточности может быть измерена с большим объемом данных. С очень маленьким объемом данных вы не можете измерить производительность многопоточного приложения. Причины:-

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

б) Когда вы создаете многопоточность, требуется переключение контекста, что также требует времени.

c) Необходимо освободить память, выделенную потокам, что также требует времени.

г) Это зависит от количества процессоров и общего объема памяти (ОЗУ) на вашем компьютере.

Поэтому, когда вы пытаетесь выполнить небольшую операцию с несколькими потоками, производительность будет такой же, как у одного потока (O / S по умолчанию назначает один поток каждому процессу, который вызывает основной поток). Так что в этом случае ваш результат идеален. Для измерения производительности многопоточной архитектуры используйте большой объем данных со сложной операцией, только тогда вы сможете увидеть различия.

20.04.2018
  • Хорошо объяснено! Спасибо! 21.04.2018
  • Используя критическое значение для большей части вычислений, вы не используете преимущества нескольких потоков. Кажется, у вас есть достаточно длинный цикл для эффективного параллельного сокращения omp. В сети должно быть размещено несколько примеров этого конкретного упражнения. 21.04.2018

  • 2

    Из-за вашего critical блока вы не можете суммировать sum параллельно. Каждый раз, когда один поток достигает раздела critical, все остальные потоки должны ждать.

    Разумным подходом было бы создать временную копию суммы для каждого потока, которую можно суммировать без синхронизации, а затем суммировать результаты из разных потоков. Openmp может сделать это автоматически с помощью предложения reduction. Итак, ваш цикл будет изменен на.

    #pragma omp parallel for reduction(+:sum)
    for (i = 0; i < num_steps; i++)
    {
        x = (i + 0.5)*step;
        sum += 4.0 / (1.0 + x * x);
    }
    

    На моей машине это выполняется в 10 раз быстрее, чем версия, использующая блок critical (я также увеличил num_steps, чтобы уменьшить влияние одноразовых действий, таких как создание потока).

    PS: Я рекомендую вам использовать <chrono>, <boost/timer/timer.hpp> или google benchmark для синхронизации вашего кода.

    22.04.2018
  • Добавьте также private(x), поскольку x определен за пределами параллельной области, он является общим, если вы явно не объявите его закрытым. 23.04.2018
  • Для определения времени OpenMP omp_get_wtime () - простой подход (который не требует никаких других заголовков или кода, кроме того, что у вас уже должно быть) 23.04.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

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

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..