Sortowanie w jednym i dwóch procesach. Problem z róznicą czasu

0

Witam

Na zadanie z programowania systemowego mam zrobić dwa programy. Jeden sortujący bąbelkowo tablicę 100000 elementową i liczący czas tej operacji. Drugi program ma wygenerować tablicę 100000elementową podzielić ją na pół i połowę przekazać do procesu potomnego a połowę pozostawić w procesie macierzystym a następnie równolegle posortować babelkową obie połówki po skończeniu proces potomny ma przesłać do macierzystego swoją połówkę i w procesie macierzystym powinno dojść do scalenia i podania czasu całej operacji. Tu jest problem otóż wg. mojego kodu sortowanie na dwóch procesach jest 4 krotnie szybsze, a z tego co mówił profesor powinno być 2 krotnie szybsze. Oto kody obu programów:

Sortowanie_jednoprocesowe:

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

int main(int argc, char *argv[])
{
 srand(time(NULL));
 int rozmiar = atoi( (argv[1]) );
 int tablica[rozmiar], i;
 for(i=0;i<rozmiar;i++)
  {
   tablica[i]=rand();
//   printf("Element numer %d = %d\n",i,tablica[i]);
  }

 void bubblesort(int table[], int size)
{
        int i, j, temp;
        for (i = 0; i<size; i++)
                for (j=0; j<size-1; j++)
                        {
                                if (table[j] > table[j+1])
                                {
                                        temp = table[j+1];
                                        table[j+1] = table[j];
                                        table[j] = temp;
                                }
                        }
}
struct timeval tim;
gettimeofday(&tim, NULL);
double t1=tim.tv_sec+(tim.tv_usec/1000000.0);
bubblesort(tablica,rozmiar);
gettimeofday(&tim, NULL);
double t2=tim.tv_sec+(tim.tv_usec/1000000.0);
printf("Uplynelo: %.6lf sekund\n", t2-t1);

}

 

Sortowanie_dwuprocesowe:

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

int main(int argc, char *argv[])
{
 
 int rozmiar = atoi( (argv[1]) );
 int tablica[rozmiar],tablica_a[rozmiar/2],tablica_b[rozmiar/2],tablica_c[rozmiar/2];
 int deskr1[2],deskr2[2], pid, status,i,j;
 srand(time(NULL)); 
 for(i=0;i<rozmiar;i++)
  {
   tablica[i]=rand();
   //printf("Element numer %d = %d\n",i,tablica[i]);
  }

 for(i=0;i<rozmiar/2;i++) tablica_a[i]=tablica[i];
 for(i=0;i<rozmiar/2;i++) tablica_b[i]=tablica[i+rozmiar/2];

 void bubblesort(int table[], int size)
 {
        int i, j, temp;
        for (i = 0; i<size; i++)
                for (j=0; j<size-1; j++)
                        {
                                if (table[j] > table[j+1])
                                {
                                        temp = table[j+1];
                                        table[j+1] = table[j];
                                        table[j] = temp;
                                }
                        }
 }

 void merge(int m, int n, int A[], int B[], int C[]) {
      int i, j, k, p;
      i = 0;
      j = 0;
      k = 0;
      while (i < m && j < n) {
            if (A[i] <= B[j]) {
                  C[k] = A[i];
                  i++;
            } else {
                  C[k] = B[j];
                  j++;
            }
            k++;
      }
      if (i < m) {
            for (p = i; p < m; p++) {
                  C[k] = A[p];
                  k++;
            }
      } else {
            for (p = j; p < n; p++) {
                  C[k] = B[p];
                  k++;
            }
      }
 }

struct timeval tim;
gettimeofday(&tim, NULL);
double t1=tim.tv_sec+(tim.tv_usec/1000000.0);

if((pipe(deskr1))==-1)
{
printf("Error pipe 1\n");
exit(-1);
}

if((pipe(deskr2))==-1)
{
printf("Error pipe 2\n");
exit(-2);
}

if((pid=fork())==-1)
{
printf("Error fork\n");
exit(-3);
}

if(pid==0)
{
 close(deskr2[1]);
 close(deskr1[0]);
 for(i=0;i<rozmiar/2;i++)
 {
  read(deskr2[0],&tablica_c[i],sizeof(int));
 }
 bubblesort(tablica_c,rozmiar/2);
 for(i=0;i<rozmiar/2;i++)
 {
  write(deskr1[1],&tablica_c[i],sizeof(int));
 }
 close(deskr2[0]);
 close(deskr1[1]);
}
else
{
 close(deskr2[0]);
 close(deskr1[1]);
 for(j=0;j<rozmiar/2;j++)
 {
  write(deskr2[1],&tablica_b[j],sizeof(int));
 }
 bubblesort(tablica_a,rozmiar/2);
 for(j=0;j<rozmiar/2;j++)
 {
  read(deskr1[0],&tablica_b[j],sizeof(int));
 }
 merge(rozmiar/2,rozmiar/2,tablica_a,tablica_b,tablica);
 close(deskr1[0]);
 close(deskr2[1]);
 gettimeofday(&tim, NULL);
 double t2=tim.tv_sec+(tim.tv_usec/1000000.0);
 printf("Uplynelo: %.6lf sekund\n", t2-t1);
 wait(&status); 
}
}
0

O(x2) > O(2*((x/2)2)) + O(merge)

0

No czyli daje to 2 krotnie szybsze wykonanie sortowania. To dlaczego w moim przypadku zysk jest 4 krotny? :D

0

Czyli co mam powiedzieć profesorowi że się myli? :D Chyba że jest jakiś inny sposób scalenia tych dwóch połówek tablicy aby czas był tylko 2 krotnie lepszy. Profesor wspominał o użyciu do scalenia qsort, tyle że z przykładów które widziałem to qsort za argument przyjmuje tylko jedną tablicę, a ja potrzebuje wrzucić dwie tablice.

0

Będzie 4 krotna różnica bo bubblesort jest O(n^2) i cudów nie zdziałasz. Idę o zakład że niesluchałeś profesora i źle go zrozumiałeś...

0

Chciałbym aby tak było. Ale wczoraj sprawdzał wykresy czasu i powiedział że różnica musi być 2 krotna na korzyść dwu procesowego sortowania. W moim przypadku różnica jest 4 krotna i jest to źle.

0

Jeśli chodzi o złożoność obliczeniową to tu i tu jest O(n^2) bo przy liniowym wzroście 'n' kwadratowo rośnie ilość operacji do wykonania.
Jeśli dla danego 'n' ilość operacji wynosi 'An2 + Bn + C' (gdzie A, B i C to jakieś stałe) to złożoność obliczeniowa jest O(n</sup>2).

Wilu88 napisał(a):

wczoraj sprawdzał wykresy czasu i powiedział że różnica musi być 2 krotna na korzyść dwu procesowego sortowania
Tak by było jeśli użyłbyś tego samego algorytmu, a nie dwa różne algorytmy. Samo użycie innego algorytmu przyspiesza sortowanie 2-krotnie. 2 procesory przyspieszają obliczenia kolejne 2 razy.

0

To jaki macie pomysł by przy użyciu łącza pipe i procesu macierzystego i potomnego posortować tablicę 100000 elementową tak aby wzrost był dwu krotny? Z tego co piszecie to fakt że podzieliłem tablicę na dwie połówki i jedną połówkę zostawiłem w procesie macierzystym a drugą przekazałem do potomnego sprawia że różnica zawsze będzie 4 krotna? I czy dwa rdzenie procesora coś zmieniają? Bo testowałem na różnych komputerach i wzrost był zawsze 4 krotny.

0

Wydawało mi się że tak, ale jeśli macie inny pomysł to chętni wysłucham.

0

Ale co wydawało Ci się, że tak? Wydawało Ci się, że bąbelkowe jest wymogiem? Przecież my nie znamy treści zadania. Użyj tych samych algorytmów w obu przypadkach, to uzyskasz pożądany efekt.

0

No a czy nie użyłem tych samych algorytmów w obu przypadkach? Oba sortowane są bublesortem. Tyle że w pierwszym programie sortowana jest cała tablica w jednym procesie. A w drugim przypadku tablica została podzielona na pół i w dwóch procesach była sortowana bublesortem.

Treść zadania:
Stwórz tablicę 100000 elementową i wykonaj sortowanie bąbelkowe wykorzystując tylko jeden proces i podaj czas trwania tego sortowania.
Druga cześć to zrobić program również tworzacy tablicę 100000 elementową następnie dzielący ja na pół i połowę sortuje proces macierzysty a drugą połowę proces potomny po skończeniu proces potomny wysyła do macierzystego swoją posortowaną połowę. I to proces macierzysty scala obie połówki i podaje całkowity czas operacji.

0

Zastosuj jakieś ludzkie sortowanie, np. merge sort lub quick sort. Wtedy nie będziesz miał przyspieszenia spowodowanego samym podzieleniem tablicy na dwie połowy i wynik powinien być zgodny z oczekiwaniami profesora. Dodatkowo użycie bubble sorta może mu się nie spodobać.

0

Wszystko zależy od komputera. Jeśli na komputerze masz jednordzeniowy procesor, to moc procesora zostanie rozłożona równo na oba procesy sortujące i uzyskasz 2 razy większą szybkość plus czas na merge: o((n/2)2)+o((n/2)2)+o(n/2).
Jeśli uruchamiasz na komputerze, z dwoma lub więcej rdzeniami, to wtedy sortowania będą wykonywane równolegle (na dwóch core-ach), ergo będziesz miał złożoność o((n/2)2)+o(n/2) czyli 4 razy lepszą od o(n2).
Może właśnie z tego wynika dysonans tego co oczekuje profesor, a co oczekujemy my (i co ty uzyskujesz).

0

OK dzięki za odpowiedź. Dorwę jakiego jedno jajowego procka i po testuje. Jak nie to przerobie to na qsorta i zobaczę jaki wynik. Wtedy sobie wybierze który wynik go bardziej satysfakcjonuje:D

0

Wystarczy, że ustawisz koligację na jeden cpu, nie musisz szukać sprzętu z jednordzeniowym prockiem

0

O(x2) > O(2*((x/2)2)) + O(merge)
Załóżmy, że O(merge) = O(2*x)
x= 10

O(x^2) = 100
O((x/2)^2) = 25
O(2*x) = 20

O(x^2):
Core 1: O(x^2) = 100

O(2*((x/2)^2)) + O(merge):
Core 1: O((x/2)^2) = 25
Core 2: O((x/2)^2) = 25
Core 1: O(2*x) = 20
Total:
Core 1: 25+20 = 45
Core 2: 25
Sum: max(Core1,Core2) = 45

Wraz ze wzrostem x będzie się polepszała złożoność czasowa algorytmu

0

Gdy x=100000 to:
algorytm A = 10 000 000 000
algorytm B = 2 500 200 000
Różnica procentowa: 399,97%

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