Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.12.2018, 21:29   #1
Yudin
Пользователь
 
Регистрация: 11.01.2018
Сообщений: 49
По умолчанию Потокозависимый вывод информации на экран

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

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

Если же во время работы потоков я вывожу на экран текст, то при любой размерности матрицы, последовательная обработка всегда будет быстрее. Я пробовал использовать cout и printf, результат тот же: если выводить текст на экран во время работы потоков, то последовательная обработка будет быстрее. Почему так, и как это исправить? Я слышал, что cout потоконезависимый, может ли это быть причиной такой работы?

Код:
#include "omp.h"
#include <iostream>
#include "time.h"
#include <ctime>
#include "windows.h"


using namespace std;
int main() {
	setlocale(LC_ALL, "russian");
	double t1, t2, t3, t4;
	int a = 0, b = 0;
	srand(time(NULL));

	int m, n;
	cout << "Введите количество строк:" << endl;
	cin >> m;
	cout << "Введите количество столбцов:" << endl;
	cin >> n;
	int *C = new int[m];
	int *B = new int[m];
	int quant = 0;	
	int **array = new int*[m];
	for (int i = 0; i < m; i++) {
		array[i] = new int[n];
		for (int k = 0; k < n; k++) {
			array[i][k] = rand() % 800-400;
		}
	}
	cout <<"Параллельная обработка 4 потоками"<<endl;
	omp_set_num_threads(4);
	t1 = omp_get_wtime();
#pragma omp parallel for reduction(+: a)
	for (int i = 0; i < m; i++) {
		quant = 0;
		if (omp_get_thread_num() != i)
		for (int k = 0; k < n; k++) {
			if (array[i][k] >= 0)
			{
				quant++;
			}
		}
		B[i] = quant;
		cout << "Поток " << omp_get_thread_num() << " обработал строку " << i + 1 << ", кол-во положительных элементов строки = " << B[i]<<endl;
	}
	t2 = omp_get_wtime();

	cout << endl << endl << "Последовательная обработка" << endl;
	t3 = omp_get_wtime();
	for (int i = 0; i < m; i++) {
		quant = 0;
		for (int k = 0; k < n; k++) {
			if (array[i][k] >= 0) {
				quant++;
			}			
		}	
		C[i] = quant;
		cout << "Поток " << omp_get_thread_num() << " обработал строку " << i + 1 << ", кол-во положительных элементов строки = " << C[i] << endl;
	}
	t4 = omp_get_wtime();

	cout <<endl<<endl<< "Время, затраченное параллельной обработкой: " << t2-t1 << " мс" << endl;
	cout << "Время, затраченное последовательной обработкой: " << t4-t3 << " мс" << endl;
	system("pause");
	return 0;
}

Последний раз редактировалось Yudin; 11.12.2018 в 21:31. Причина: опечатался
Yudin вне форума Ответить с цитированием
Старый 12.12.2018, 12:06   #2
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Yudin Посмотреть сообщение
Я слышал, что cout потоконезависимый, может ли это быть причиной такой работы?
конечно может)
потоки утыкиваются в блокировки, конкурируя за вывод.
(в случае с std::cout, конкуренция за доступ к буферу за каждый символ)

по сути, они выстраиваются последовательно,
что сильно сводит на нет всю идею параллельных вычислений.
так что перфоманс вам нужно замерять "в слепую".

зы:
для выполнения честных замеров,
необходимо делать два независимых приложения:
одно только с последовательными вычислениями,
второе - только с параллельными.

если же запускать сначала одно,
потом другое в рамках одного приложения,
то можно нарваться на эффект "прогретой памяти".
результаты тестов начинают зависеть от того,
в какой очередности их запускают.
_Bers вне форума Ответить с цитированием
Старый 12.12.2018, 16:32   #3
Yudin
Пользователь
 
Регистрация: 11.01.2018
Сообщений: 49
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
по сути, они выстраиваются последовательно,
А почему если они выстраиваются по сути последовательно, то реальная последовательна обработка справляется быстрее? Из-за того, что потоки тратят время на то, чтобы понять кто из них будет выводить текст?


Цитата:
Сообщение от _Bers Посмотреть сообщение
конечно может)
потоки утыкиваются в блокировки, конкурируя за вывод.
И не существует ли каких-нибудь альтернатив для параллельного вывода текста на экран во время работы потоков? Важно, чтобы текст выводился во время работы потоков.
https://stackoverflow.com/questions/...ut-thread-safe
Это не панацея в моём случае? Я так понял, там описали как сделать так, чтобы сиауты потоков друг на друга не налезали, но это ведь не сократит время работы?

Последний раз редактировалось Alex11223; 06.05.2019 в 17:27.
Yudin вне форума Ответить с цитированием
Старый 13.12.2018, 11:41   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Yudin Посмотреть сообщение
А почему если они выстраиваются по сути последовательно, то реальная последовательна обработка справляется быстрее?
может быть 100500 различных причин.
одна из которых - прогретая память.


Цитата:
Сообщение от Yudin Посмотреть сообщение
И не существует ли каких-нибудь альтернатив для параллельного вывода текста на экран во время работы потоков? Важно, чтобы текст выводился во время работы потоков.
а как вы себе это вообще представляете?

вы вообще понимаете смысл идеи "многопоточного программирования" ?
есть несколько потоков, которые исполняются одновременно.
параллельно друг другу.

вот есть 1 сортир, и 10 мужиков. все мужики хотят в туалет.
вот как хотя бы чисто теоретически, они могли бы сделать это одновременно?
унитаз то только один.

хотите устранить конкуренцию за ресурс - дайте каждому мужику его личный унитаз.

то бишь, каждый поток пусть выводит данные не в консоль,
а складирует куда нибудь в своём персональном хранилище.

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

Цитата:
Сообщение от Yudin Посмотреть сообщение
Это не панацея в моём случае?
нет конечно.

более того, представленная там идея ещё ухудшит вашу ситуацию.

если в простом случае потоки конкурируют за буковку,
то в случае с synchronized_ostream конкуренция будет
за всю выводимую строчку.


Цитата:
Сообщение от Yudin Посмотреть сообщение
Я так понял, там описали как сделать так, чтобы сиауты потоков друг на друга не налезали, но это ведь не сократит время работы?
нет никаких "сиаутов потоков".
есть один единственный глобальный объект std::cout.
у него внутри - потоко-безопасный буфер.

буфер блокируется, принимает очередную порцию буковок,
выводит в консоль, блокировка снимается.

на практике это означает, что нам гарантируют,
что мы можем безопасно писать из нескольких потоков в std::cout.
однако, блокировка не на все сообщение, а на отдельные кусочки (буковки)

поэтому, если один поток запишет "hello", а другой "world",
буковки из разных потоков могут прийти в разнобой,
и итоговый текст может спутаться: "helworlold"

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

в результате получается картинка:

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


в результате:
мужики выстраиваются в честную очередь, и ждут.

Последний раз редактировалось Alex11223; 06.05.2019 в 17:26.
_Bers вне форума Ответить с цитированием
Старый 16.12.2018, 17:19   #5
Yudin
Пользователь
 
Регистрация: 11.01.2018
Сообщений: 49
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
вот есть 1 сортир, и 10 мужиков. все мужики хотят в туалет.
Ну ходят они все в туалет по очереди, да, понял, спасибо. И текст в консоли последовательно появляется. Но если так, то как это возможно:
Цитата:
Сообщение от _Bers Посмотреть сообщение
буковки из разных потоков могут прийти в разнобой,
и итоговый текст может спутаться: "helworlold"
Мужик сходил немного в туалет, дал другому, а потом обратно зашёл?
Yudin вне форума Ответить с цитированием
Старый 16.12.2018, 18:13   #6
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Цитата:
Сообщение от Yudin Посмотреть сообщение
Но если так, то как это возможно:
Цитата:
Сообщение от _Bers Посмотреть сообщение
однако, блокировка не на все сообщение, а на отдельные кусочки (буковки)
Вы посты читайте полностью.
p51x на форуме Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вывод на экран информации о жестком диске ученик_програмиста Win Api 5 27.05.2017 23:42
вывод в див имен из бд и при нажатии вывод в отдельный див дополнительной информации об этом имени / PHP и базы данных looni123 JavaScript, Ajax 3 03.04.2014 21:26
вывод информации на экран о состоянии памяти на текущем диске А(assembler) alien9356 Фриланс 2 15.06.2009 15:41
Вывод информации на экран Linel PHP 10 23.02.2009 12:46
вывод на экран информации о маршрутах, начинающихся или кончающихся в пункте Sergeo_89 Паскаль, Turbo Pascal, PascalABC.NET 4 07.12.2008 21:00