Wielowątkowość - thread c++

0

Witam serdecznie. Dostałem takie zadanie aby napisać program który wyszuka minimum w tablicy (wielowątkowo - liczba wątków ustalana na etapie kompilacji). Wykorzystałem tutaj tablice wątków, alokowaną dynamicznie. Tworze nowe wątki poprzez new aczkolwiek nie mam pojęcia jak zrobić żeby program czekał aż wszystkie te wątki sie skończą i dopiero wtedy przeszukał tablice pomocniczą w której znajdują się min znalezione przez każdy wątek. Zamieszczam kod za wszelkie rady będę bardzo wdzięczny :) Czytałem troche o join ale nie mam pojęcia jak tutaj z tego skorzystać. Przy normalnym tworzeniu wątków np: thread t1(xx) thread t2(xxx) nie ma problemu bo wystarczy zrobić t1.join() t2.join().

#include <iostream>
#include <thread>
#include <ctime>
using namespace std;
#define lbwatkow 5
#define N 100

int Tab[N];
int TabMin[lbwatkow];

void Wypelnij();
void MinWatek(int poczatek, int koniec, int nr_watku);
void Szukajmin();
void znajdzmin();

int main()
{
	Wypelnij();
	Szukajmin();
	getchar();
}

void Wypelnij()
{
	for (int i = 0; i < N; ++i)
		Tab[i] = rand() % 100 - 50;
}

void MinWatek(int pocz, int kon, int nr_watku)
{
	int min = Tab[pocz];
	for (int i = 0; i < kon; ++i)
	{
		if (Tab[i] < min)
			min = Tab[i];
	}
	TabMin[nr_watku] = min;
}
void Szukajmin()
{
	int Podzialy = N / lbwatkow;
	thread TabWatkow[lbwatkow];
	thread *wskTab = TabWatkow;
	for (int i = 0; i < lbwatkow; ++wskTab, ++i)
	{
		wskTab = new thread(MinWatek, i*Podzialy, (i + 1)*Podzialy, i); // tworzone nowe watki wraz z podzialami do szukania
	}
	znajdzmin();
}
void znajdzmin() // szukanie minimum w tablicy min. ktore znalazly watki
{
	int min = TabMin[0];
	for (int i = 1; i < N; ++i)
	{
		if (TabMin[i] < min)
			min = TabMin[i];
	}
	cout << "Minimum = " << min << endl;
} 
2

Po ludzku?
Użyj boost::thread_group group; wraz z group.join_all();

Po mniej ludzku:
Skoro i tak musisz poczekać na >wszystkie< wątki, to nie interesuje Cie to, że jesteś blokowany.
Tak więc zwykła pętelka wystarczy.

for(auto &thread : threads)
    thread.join();
0

Troche nie bardzo rozumiem. Dołożyłem pętle za pętlą która tworzy wątki i nic to nie pomogło. Próbowałem równiez zaraz po utworzeniu wątku zrobić TabWatkow[i].join(); ale tak samo nic..

1
Zimny Młot napisał(a):

Troche nie bardzo rozumiem. Dołożyłem pętle za pętlą która tworzy wątki i nic to nie pomogło. Próbowałem równiez zaraz po utworzeniu wątku zrobić TabWatkow[i].join(); ale tak samo nic..

No to zobaczmy:

thread TabWatkow[lbwatkow];

Tworzy 5 obiektów nie reprezentujących żadnych wątków. To wyjaśnia:

Próbowałem równiez zaraz po utworzeniu wątku zrobić TabWatkow[i].join(); ale tak samo nic

thread *wskTab = TabWatkow;

wskTab wskazuje na początek tablicy TabWatkow.

for (int i = 0; i < lbwatkow; ++wskTab, ++i)
{
    wskTab = new thread(MinWatek, i*Podzialy, (i + 1)*Podzialy, i); // tworzone nowe watki wraz z podzialami do szukania
}

w każdym obiegu pętli wskTab wskazuje na nowy adres, który nie ma nic wspólnego z TabWatkow, więc jeśli potem próbujesz robić join() za pomocą TabWatkow, to raczej marne szanse, że się uda.

0

Ok rozumiem to, że w kazdym obiegu pętli wskTab wskazuje na nowy adres, ale dlaczego nie moge w każdym obiegu podłączyć aktualnie tworzonego wątku (po new) poprzez join().
Probowałem jeszcze po stworzeniu wszystkich wątków (za pętlą) jeszcze raz przejść i podłączyć wszystkie poprzez:

for(auto &thread : TabWatkow)
    thread.join();

Ale również nie udało się.

0

Czy takie rozwiązanie jest poprawne? Po prostu w pętli dodałem wskTab->join();

#include <iostream>
#include <thread>
#include <ctime>
using namespace std;
#define lbwatkow 5
#define N 1000
int Tab[N];
int TabMin[lbwatkow];

void Wypelnij();
void MinWatek(int poczatek, int koniec, int nr_watku);
void Szukajmin();
void znajdzmin();

int main()
{
	Wypelnij();
	Szukajmin();
	getchar();
}

void Wypelnij()
{
	for (int i = 0; i < N; ++i)
		Tab[i] = rand() % 100 - 50;
}

void MinWatek(int pocz, int kon, int nr_watku)
{
	int min = Tab[pocz];
	for (int i = 0; i < kon; ++i)
	{
		if (Tab[i] < min)
			min = Tab[i];
	}
	TabMin[nr_watku] = min;
	cout << "Watek numer: " << nr_watku << " znalazl minimum i zakonczyl prace. " << min << endl;
}
void Szukajmin()
{
	int Podzialy = N / lbwatkow;
	thread TabWatkow[lbwatkow];
	thread *wskTab = TabWatkow;
	for (int i = 0; i < lbwatkow; ++wskTab, ++i)
	{
		wskTab = new thread(MinWatek, i*Podzialy, (i + 1)*Podzialy, i); // tworzone nowe watki wraz z podzialami do szukania
		wskTab->join();
	}
	znajdzmin();

}
void znajdzmin() // szukanie minimum w tablicy min. ktore znalazly watki
{
	int min = TabMin[0];
	for (int i = 1; i < N; ++i)
	{
		if (TabMin[i] < min)
			min = TabMin[i];
	}
	cout <<endl << "===== Minimum = " << min << endl;
}
0
Zimny Młot napisał(a):

Probowałem jeszcze po stworzeniu wszystkich wątków (za pętlą) jeszcze raz przejść i podłączyć wszystkie poprzez:

for(auto &thread : TabWatkow)
    thread.join();

Ale również nie udało się.

twonek napisał(a):

w każdym obiegu pętli wskTab wskazuje na nowy adres, który nie ma nic wspólnego z TabWatkow, więc jeśli potem próbujesz robić join() za pomocą TabWatkow, to raczej marne szanse, że się uda.

Po co w ogóle bawisz się ohydnym wskaźnikiem skoro i tak masz statyczną tablicę?

thread TabWatkow[ILE_WATKOW];
for (int i = 0; i < ILE_WATKOW; ++i)
{
	TabWatkow[i] = thread(MinWatek, i*Podzialy, (i + 1)*Podzialy, i);
	TabWatkow[i].join();
}
3

Zastosowanie join w pętli czyni użycie wątków kompletnie bezsensownym.

0
0x666 napisał(a):

Zastosowanie join w pętli czyni użycie wątków kompletnie bezsensownym.

Dlaczego?

Dzięki za pomoc dla kolegi wyżej, już chyba załapałem o co chodziło :)

1

Dlatego, że wszystko, pomimo użycia kilku wątków, i tak wykonuje się sekwencyjnie. Tworzysz wątek, czekasz aż się wykona, po czym znowu tworzysz wątek dla następnego przedziału i czekasz, itd. Równie dobrze mógłbyś wywalić te wątki, a w pętli od razu wywoływać MinWatek. Takie rozwiązanie byłoby szybsze ;)

Odpal ILE_WATKOW wątków w jednej pętli, a w drugiej czekaj na ich zakończenie.

0

Czekać poprzez join czy jest jakaś metoda która sprwadza, że wątek się zakończył?
Dzięki za informacje, faktycznie wszystko wykonuje się po kolei więc traci to sens.

0

Zmieniłem na coś takiego:

	for (int i = 0; i < lbwatkow;  ++i)
	{
		TabWatkow[i] = thread(MinWatek, i*Podzialy, (i + 1)*Podzialy, i); // tworzone nowe watki wraz z podzialami do szukania
		//TabWatkow[i].join();
		/*wskTab->join();*/
	}
	for (int i = 0; i < lbwatkow; ++i)
	{
		TabWatkow[i].join();
	}

i wydaje się działać tak jak powinno :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1