Program dwuwątkowy wysypuje się

0

Napisałem program do mnożenia macierzy (dwie pary w dwóch osobnych wątkach). Chodzi głównie o to żeby porównać czas działania z jednowątkowym (dlatego tyle pętli robię). Niestety nie dość, że dwuwątkowy działa mi dłużej od jednowątkowego, to jeszcze lubi się wysypać w momencie obliczeń. Co może być w tym kodzie nie tak?
Oto i on:

#include <stdio.h> 
#include <stdlib.h>
#include <windows.h>
#include <time.h>

	clock_t start, finish; 
	double duration;
    int w,k,i,j,x,y; 
	int * tab_aa,* tab_bb,* tab_cc,* tab_dd; 

DWORD WINAPI ThreadProc1(void* param)  
{  
	for(int p=0; p<9000; p++)
	{
    for(i=0; i<x; i++) 
     for(j=0; j<y; j++) 
      *(tab_cc+i*y+j)=0; 
  
    for(i=0; i<x; i++) 
     for(j=0; j<y; j++) 
       for(k=0; k<y; k++) 
        *(tab_cc+i*y+j) += *(tab_aa+i*y+k) * *(tab_aa+k*y+j); 
	}			
    return TRUE;   
}

DWORD WINAPI ThreadProc2(void* param)  
{  
	for(int p=0; p<5000; p++)
	{
    for(i=0; i<x; i++) 
     for(j=0; j<y; j++) 
      *(tab_dd+i*y+j)=0; 
  
    for(i=0; i<x; i++) 
     for(j=0; j<y; j++) 
       for(k=0; k<y; k++) 
        *(tab_dd+i*y+j) += *(tab_bb+i*y+k) * *(tab_bb+k*y+j); 
	}		
    return TRUE;   
}

  int main() 
  { 
	DWORD threadID,threadID1;  
	DWORD thread_arg = 4;
	DWORD  threadId[2];
	HANDLE hThreads[2]; 
	HANDLE hThread1,hThread;
  
    printf("MNOZENIE MACIERZY KWADRATOWYCH 3-WYMIAROWYCH\n\n"); 
	x=2;
	y=2;

    tab_aa = (int *)malloc(sizeof(int)*x*y); 
    tab_bb = (int *)malloc(sizeof(int)*x*y);
    tab_cc = (int *)malloc(sizeof(int)*x*y); 
    tab_dd = (int *)malloc(sizeof(int)*x*y); 
	
	printf("Wprowadz wartosci do pierwszej pary macierzy:\n"); 
    for(i=0; i<x; i++) 
     { 
      printf("Wiersz %d\n", i+1); 
      for(j=0; j<y; j++) 
         scanf_s("%d",tab_aa+i*y+j); 
     }

	printf("Wprowadz wartosci do drugiej pary macierzy:\n"); 
    for(i=0; i<x; i++) 
     { 
      printf("Wiersz %d\n", i+1); 
      for(j=0; j<y; j++) 
         scanf_s("%d",tab_bb+i*y+j); 
     }
	 	
	start = clock(); 
	//pierwsza para
	hThreads[0] = CreateThread( NULL, 0, ThreadProc1, NULL, 0, &threadId[0] );
	//druga para
	hThreads[1] = CreateThread( NULL, 0, ThreadProc2, NULL, 0, &threadId[1] );
	
	WaitForMultipleObjects(2,hThreads,TRUE,INFINITE);
  
	for(i=0;i<2;i++) CloseHandle(hThreads[i]);

	finish = clock();
    duration = (double)(finish - start)/CLOCKS_PER_SEC; 

	printf("Wynik mnozenia pierwszej pary macierzy:\n");
	for(i=0; i<x; i++) 
		for(j=0; j<y; j++) 
			printf("%d %d = %d\n",i+1,j+1,*(tab_cc+i*y+j)); 

	printf("Wynik mnozenia drugiej pary macierzy:\n");
	for(i=0; i<x; i++) 
		for(j=0; j<y; j++) 
			printf("%d %d = %d\n",i+1,j+1,*(tab_dd+i*y+j));

	printf( "\n\nCzas wykonywania programu %3.6f s\n", duration ) ;
	
	free(tab_aa);
	free(tab_bb);
    free(tab_cc);
	free(tab_dd);
  
    system("PAUSE"); 
    return 0; 
  } 

P.S. Najlepsze jest to, że po lekkiej modyfikacji kodu pod Linuxa, program działa IDEALNIE (na Fedorze 8)

0

Nie widze tu zadnej synchronizacji dostepu do pamieci tych tablic. To dlatego to sie sypie.

0

Hahaha!!!.
popatrz na zmienne: p,i,j,k !!!!
każda z nich jest modyfikowana przez wątki, a to są zmienne globalne!
Efekt jest taki, że wątki się gryzą bo o dostęp do tych zminnych.
Przenieś definicje tych zmiennych do ciał funkcji i powinno być dobrze.
Nie ma powodu by były to zmienne globalne, więc synchronizacja jest niekonieczna.

0
for(i=0; i<x; i++)
     for(j=0; j<y; j++) 
          *(tab_cc+i*y+j)=0; 

A nie tak przypadkiem:

*(tab_cc+j*y+i)=0; 
0

Szczerze mówiąc jak widzę jaki reprezentujesz poziom umiejętności to dam ci dobrą radę:
NIE UŻYWAJ WIELOWĄTKOWOŚCI!!!
Przynajmniej dotąd dopóki nie będziesz umiał dostatecznie programować bez wątków.
Wielowątkowość wymaga już większego zrozumienia co kiedy i gdzie się dzieje.

0
MarekR22 napisał(a)

Szczerze mówiąc jak widzę jaki reprezentujesz poziom umiejętności to dam ci dobrą radę:
NIE UŻYWAJ WIELOWĄTKOWOŚCI!!!
Przynajmniej dotąd dopóki nie będziesz umiał dostatecznie programować bez wątków.
Wielowątkowość wymaga już większego zrozumienia co kiedy i gdzie się dzieje.

Heh ... jak masz projekt do oddania to nie ma zmiłuj ...
Ok ... w każdym razie sam znalazłem przyczynę wysypywania się programu ... pętla, która zwielokratniała mi funkcję mnożenia (for p) musi być typu "long int" ... teraz program się nie sypie :)
Aha i przepraszam, jeśli kogoś uraziłem swoją niewiedzą ... niestety projekty "na wczoraj" wymagają szybkiej (często nieuważnej) pracy ...

0

Ciekawe czy bedzie dzialac na innym procku, z inna pamiecia itd. [diabel]

0
PSQ napisał(a)

Heh ... jak masz projekt do oddania to nie ma zmiłuj ...
Ok ... w każdym razie sam znalazłem przyczynę wysypywania się programu ... pętla, która zwielokratniała mi funkcję mnożenia (for p) musi być typu "long int" ... teraz program się nie sypie :)
Aha i przepraszam, jeśli kogoś uraziłem swoją niewiedzą ... niestety projekty "na wczoraj" wymagają szybkiej (często nieuważnej) pracy ...

co do tego ma long? Twoja zmienna p nie przekracza wartości maksymalnych int-a, więc musiałeś coś pokręcić lub nie podałeś prawidłowo listingu programu.
Nie chodzi tu o niewiedzę, ale styl kodowania. Nadmierne używanie zmiennych globalnych jest naprawdę złym zwyczajem i właśnie to wkopało cię w kłopoty (patrz co napisałem wcześniej).

0
MarekR22 napisał(a)

co do tego ma long? Twoja zmienna p nie przekracza wartości maksymalnych int-a, więc musiałeś coś pokręcić lub nie podałeś prawidłowo listingu programu.
Nie chodzi tu o niewiedzę, ale styl kodowania. Nadmierne używanie zmiennych globalnych jest naprawdę złym zwyczajem i właśnie to wkopało cię w kłopoty (patrz co napisałem wcześniej).

Przyznaję, że mogłem wkopać z tymi zmiennymi (i tak najważniejsze, że mam zaliczony projekt), ale właśnie po dopisaniu typu long program przestał się sypać przy obliczeniach ... pętle musiałem mieć duże (rzędu kilku milionów) bo musiałem porównać czas z programem jednowątkowym. Dzięki ogólnie za sugestie ... zawsze pomoże mi to w następnych projektach :)

0

Dobra jak ta pętla for dla p była do kliku milionów to zgoda, long pomoże (zamieściłeś kod nie adekwatny do twojego problemu).
Ale jeśli nie przeniosłeś tych zmiennych i, j, k tak by były lokalne, to gwarantuje ci, że wynik możenia nie był za każdym razem prawidłowy.
Jeśli zaliczyłeś to bez tej poprawki, to musi wynikać to z tego, że nauczyciel wie niewiele więcej od ciebie lub traktuje prowadzanie zajęć na odchrzań się.

0
MarekR22 napisał(a)

Jeśli zaliczyłeś to bez tej poprawki, to musi wynikać to z tego, że nauczyciel wie niewiele więcej od ciebie lub traktuje prowadzanie zajęć na odchrzań się.

Tyz prowda.

0

w tym momencie akurat bardziej interesowało go inicjowanie wątków niż implementowanie zmiennych ... sam fakt pisałem ten projekt w nocy (tak to jest, jak grupa nie chce współpracować) ... fakt też, że gostek bardziej trawi linuxa (windowsa nie tykał od 10 lat ;) ) ... a akurat pod linuxem zauważyłem, że zmienne zrobiłem lokalne :). Ok w każdym razie dzięki za wszelkie sugestie :)

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