• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

program z dowolna liczba watkow

VPS Starter Arubacloud
+1 głos
390 wizyt
pytanie zadane 25 października 2021 w C i C++ przez krukWiesio Początkujący (400 p.)

Witam, mam problem ponieważ napisałem taki program który ma liczyć sumę szeregu przy użyciu dowolnej liczby wątków jednakże mój program chyba działa niepoprawnie ponieważ im więcej wątków daje tym wolnej sie wykonuje, Prosze o pomoc w tej sprawie.

 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#define MAXL 100000000
#define LICZBAW 2
#define POCZATEK 1

double sumac = 0;
double start = 0;
double koniec = MAXL/LICZBAW; 


double suma(int p,int k) {
     double s=0;
     int i;
     for (i=p;i<=k;i++) s=s+(1.0/i)*(1.0/i);
     return s;
}

void* p (void* l) {
     double s=0;
     s=suma(start+1,koniec);
     start = koniec;
     koniec += koniec;
     sumac+=s;
     return 0;     
}


int main () {

	pthread_t w[LICZBAW];
	int i=0;

	
	for(; i<LICZBAW; i++){
		pthread_create(&w[i], 0, p, NULL);
		pthread_join(w[i], NULL);
	}
	
	printf("wynik: %.15lf", sumac);
	
	return 0;
}

 

2 odpowiedzi

0 głosów
odpowiedź 25 października 2021 przez mokrowski Mędrzec (155,460 p.)
wybrane 19 listopada 2021 przez krukWiesio
 
Najlepsza

Przeanalizuj...

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#define THREADS_COUNT 8
#define ELEMENTS_COUNT 32768

struct work {
    int start;
    int stop;
    int result;
};

int dumb_function(int start, int stop) {
    int my_sum = 0;
    for (int i = start; i < stop; ++i) {
        my_sum += i * 2;
    }
    return my_sum;
}

void* work_thread (void* range) {
    struct work * thread_range = (struct work *)(range);
    /* Debug check... */
    /* printf("work_thread [%d, %d)\n", thread_range->start, thread_range->stop); */
    thread_range->result = dumb_function(thread_range->start, thread_range->stop);
    return NULL;
}

int main(void) {

    pthread_t threads_table[THREADS_COUNT] = {0};
    struct work ranges[THREADS_COUNT] = {0};
    int my_sum = 0;

    int offset = ELEMENTS_COUNT / THREADS_COUNT;

    for (int i = 0; i < THREADS_COUNT; ++i){
        /* range -> [start, stop) */
        ranges[i].start = i * offset;
        ranges[i].stop = (i + 1) * offset;
        pthread_create(&(threads_table[i]), 0, work_thread, (void *)&(ranges[i]));
    }

    for (int i = 0; i < THREADS_COUNT; ++i) {
        pthread_join(threads_table[i], NULL);
        my_sum += ranges[i].result;
    }

    printf("result: %d\n", my_sum);

    return EXIT_SUCCESS;
}

 

komentarz 26 października 2021 przez mokrowski Mędrzec (155,460 p.)
edycja 26 października 2021 przez mokrowski
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#define MAXL 100000000
#define LICZBAW 2
#define OFFSET ((MAXL) / (LICZBAW))

double sums[LICZBAW];

double suma (int p,int k) {
    double s=0;
    int i;
    for (i=p; i<k; ++i)
    {
        s=s+(1.0/i)*(1.0/i);
    }
    return s;
}

void* p (void* idx) {
    long index = (long)idx;
    double s;

    s = suma(index * OFFSET, (index + 1) * OFFSET);

    sums[index - 1] = s;
    return NULL;
}

int main (void) {

    pthread_t w[LICZBAW];
    long i;

    for(i = 0; i < LICZBAW; ++i) {
        pthread_create(&w[i], 0, p, (void*)(i + 1));
    }

    double sum = 0;
    for(i = 0; i < LICZBAW; ++i)
    {
        pthread_join(w[i], NULL);
        sum += sums[i];
    }

    printf("Suma: %.15lf\n", sum);

    return EXIT_SUCCESS;
}

Nie do końca rozumiem co chcesz osiągnąć indeksem 0. Jeśli wejdzie on do obliczeń, to wynik będzie inf ze względu na dzielenie przez zero. Jeśli jednak masz inny pomysł niż ja założyłem, popraw. Linia 38 i 28 i ew. inne...

komentarz 26 października 2021 przez krukWiesio Początkujący (400 p.)

@mokrowski, Coś źle liczy sumę ponieważ suma zawsze powinna wynosić tyle samo po zmianie liczby wątków a jedynie to czas wykonywania się powinien zmieniać, przynajmniej tak rozumiem zadanie. Nie mam pojęcia już w czym może być problem 

"Uogólnić program współbieżny żeby mógł być wykonywany przez dowolną liczbę wątków. Sprawdzić dla jakiej liczby wątków program wykonuje się najszybciej. Wyjaśnić dlaczego dalsze zwiększanie liczby wątków nie wpływa na przyspieszenie programu."

komentarz 26 października 2021 przez mokrowski Mędrzec (155,460 p.)

1. Napisałem Ci że nie wiem jak masz traktować indeks o wartości 0. Dla zera, wykonywane jest dzielenie przez zero. Popraw więc kod tak aby było wiadomo o co chodzi.

Proszę, przy założeniu że masz wyłącznie sumowanie (a nie niedoprecyzowany dla zera ciąg),  kod zwraca wynik stabilnie:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#define MAXL 100000000
#define LICZBAW 8
#define OFFSET ((MAXL) / (LICZBAW))

double sums[LICZBAW];

double suma (int p,int k) {
    double s=0;
    int i;
    for (i=p; i<k; ++i)
    {
        s += i;
        //s=s+(1.0/i)*(1.0/i);
    }
    return s;
}

void* p (void* idx) {
    long index = (long)idx;
    double s;

    s = suma(index * OFFSET, (index + 1) * OFFSET);

    sums[index] = s;
    return NULL;
}

int main (void) {

    pthread_t w[LICZBAW];
    long i;

    for(i = 0; i < LICZBAW; ++i) {
        pthread_create(&w[i], 0, p, (void*)(i));
    }

    double sum = 0;
    for(i = 0; i < LICZBAW; ++i)
    {
        pthread_join(w[i], NULL);
        sum += sums[i];
    }

    printf("Suma: %.15lf\n", sum);

    return EXIT_SUCCESS;
}

Zmień ilość wątków a sam zobaczysz. Wniosek, podział pracy jest wykonywany poprawnie przy założeniu że 0 (zero) nie wpływa na wynik (tu prostego sumowania). W Twoim ciągu, wpływa i to zdecydowanie :)

2. Liczysz na double/floatach i błędy się kumulują. Jak chcesz robić to zgodnie z zasadami (sumowanie), to jest od tego algorytm Kahan'a który redukuje błędy sumowania: https://en.wikipedia.org/wiki/Kahan_summation_algorithm

komentarz 26 października 2021 przez krukWiesio Początkujący (400 p.)
Źle zrozumiałem w takim razie co do tego 0 ale udało mi się do tego dojść samemu po wnikliwej analizie. Wielkie dzięki za pomoc i poświęcony czas. Trochę mi to rozjaśniło temat :D
komentarz 28 października 2021 przez mokrowski Mędrzec (155,460 p.)
No to zaznacz odpowiedź jako wartościową :)
0 głosów
odpowiedź 25 października 2021 przez Oscar Nałogowiec (29,290 p.)
Twoje wątki nie wykonują się współbieżnie.  Kolejno, w pętli. uruchamiasz wątek i czekasz na jego zakończenie. Lepiej najpierw uruchamić wszystkie a potem poczekać aż się wszystkie zakończą - czyli w jednej pętli create a w drugiej join.

Samej metody obliczeń nie analizowałem, tak ogólnie nie wszystkie zadania dają się przyspieszyć rozbijając je na wiele wątków.
komentarz 25 października 2021 przez krukWiesio Początkujący (400 p.)
wtedy w ogóle wynik daje 0
komentarz 25 października 2021 przez Oscar Nałogowiec (29,290 p.)
Jak wspominałem, nie analizowałem samej poprawności obliczeń, w sumie nie podałeś co chcesz obliczyć. Ale widać, że używasz zmiennych globalnych bez żadnego zabepieczenia pomiędzy wątkami. Wątki będą sobie wzajemnie nadpisywać te zmienne. Musisz jakoś określić którą część zadania ma wykonać każdy wątek, przekazać mu to, najlepiej w parametrach i uruchomić. Być może główny program będzie musiał jakoś pozbierać te częściowe wyniki.
komentarz 25 października 2021 przez krukWiesio Początkujący (400 p.)
właśnie wydaje mi sie ze przydzielam kazdemu z watkow zakres dzialania aczkowiek zielony w tym jeszcze jestem wiec mogę się mylićdlatego prosze o pomoc bardziej doświadczonych :D
komentarz 25 października 2021 przez Oscar Nałogowiec (29,290 p.)
Zaprojektowałeś przetwarzanie w sposób, który nie da się wykonać współbieżnie. Wykonujesz wątki kolejno, dlatego im ich więcej tym program dłużej trwa. Jeśli chcesz sensownie wykorzystać wielowątkowość musisz przygotować przetwarzanie tak, by każdy wątek mógł działać równocześnie. Zwykle każdy wątek działa na własnych zmiennych - mogą to być zmienne lokalne w funkcji wątku (ale te znikają po zakończeniu funkcji) mogą też być dostarczone "z zewnątrz". Masz już tablicę "w" - po jednej zmiennej na wątek. Zmień ją na tablicę struktur i niech każda struktura poza phtread_t zawiera więcej pól, będą to zmienne których wątek może używać "na wyłączność". Trzeba będzie też do każdego wątku przekazać indeks w tablicy/wskaźnik na strukturę, by wiedział na których zmiennych ma działać. Jeśli w twoim szeregu można policzyć dowolny zakres to niech każdy wątek liczy rozdzielny od innych zakres, zapamiętuje wynik w swoich zmiennych (ta struktura) a potem program główny po sumuje i już.

Podobne pytania

+1 głos
2 odpowiedzi 538 wizyt
0 głosów
0 odpowiedzi 235 wizyt
0 głosów
1 odpowiedź 162 wizyt

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...