Sunteți pe pagina 1din 18

Universitatea din Pitesti

Facultatea de Electronica, Comunicatii si Calculatoare


Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

Tema A.P.D.
Sortarea bitonica

1.Descrierea tehnicii de sortare bitonica:

Problema sortarii unei secvente bitone se reduce de la sortarea unei secvente de lungime
n la sortarea a doua secvente de dimensiune n/2.
Ce insemna bitonic?
Acest lucru conteaza deoarece retelele de dreapta impart o secventa bitonica in doua
secvente bitonice. Mai mult orice element prima secventa bitonica este mai mic deca orice
element din a doua.
Pentru a sorta o secventa de n elemente:
- Doua elemente formeaza o secventa bitona
- Orice secventa nesortata este o concatenare de secvente bitone de lungime 2
- Idea de sortare: Combinarea intr-o secventa mai larga pana se obtine o secventa bitona
de lungime n

1
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

2. Algoritm de sortare bazat pe interclasarea de secvente bitone


Conventii:
- A[0:n-1] este tabloul de intrare
- d este un parametru binar ce specifica ordinea de sortare crescatoare (d=0) sau
descrescatoare (d=1) a cheilor de sortare
- COMP_EX(x,y;d) desemneaza operatie primitive care aranjeaza doua numere x si y in
ordinea specificata in d

Pseudocod pentru algoritmul Batcher de sortare bitonica (SECVENTIAL)


proc sortare_bitonica(A[i;i+b-1],d)
begin
if (b=2) (A[i],A[i+1]) = COMP_EX(A[i],A[i+1];d)
else
sortare_bitonica(A[i:i+b/2-1],0);
sortare_bitonica(A[i+b/2:i+b-1],1);
interclasare_bitonica(A[i:i+b-1],d);
end
2
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

proc interclasare_bitonica(A[i:i+b-1,d)
begin
if (b=2) (A[i],A[i+1]) = COMP_EX(A[i],A[i+1],d);
else
for j=0 ; j<= b/2 ;j++
(A[i+j],A[i+b/2+j]) = COMP_EX(A[i+j],A[i+b/2+j],d);
interclasare_bitonica (A[i:i+b/2-1],d);
interclasare_bitonica (A[i+b/2:i+b-1],d);
end

3. Metode de paralelizare.

3
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

4
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

5
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

6
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

7
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

8
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

4. Implentarea software a sortarii bitonice in C++ utilizand standardul MPI


// dependete de librarie
#include <stdio.h> // Printf
#include <time.h> // Timer
#include <math.h> // Logarithm
#include <stdlib.h> // Malloc
#include "mpi.h" // MPI Library
#include "bitonic.h"

#define MASTER 0 // face procesarea finala


#define OUTPUT_NUM 10 // numarul de elemente

// var. globale
double timer_start;
double timer_end;
int process_rank;
int num_processes;
int * array;
int array_size;

9
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

int main(int argc, char * argv[]) {


int i, j;
// initializarea mpi , nr procese , rang-ul proceselor
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_processes);
MPI_Comm_rank(MPI_COMM_WORLD, &process_rank);

// initializare dimensiune vector


array_size = atoi(argv[1]) / num_processes;
array = (int *) malloc(array_size * sizeof(int));

// generare de elemente intamplatoare , realizata de fiecare process


// mai putin de lucru pentru MASTER
srand(time(NULL)); // Needed for rand()
for (i = 0; i < array_size; i++) {
array[i] = rand() % (atoi(argv[1]));
}
// operarea este blocata pana cand toate procesele au terminat de generat numere aleatoare
MPI_Barrier(MPI_COMM_WORLD);

// Incepe alg. sortare bitonica


// dimensiunea cubului
int dimensions = (int)(log2(num_processes));

// Porneste timer-ul pentru prima operatie/iteratie


if (process_rank == MASTER) {

10
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019
printf("Numarul de procese este: %d\n", num_processes);
timer_start = MPI_Wtime();
}

// Sortare secventiala , quicksort


qsort(array, array_size, sizeof(int), ComparisonFunc);

// Sortarea Bitonica
for (i = 0; i < dimensions; i++) {
for (j = i; j >= 0; j--) {
//id-ul procesului curent este par si elementul i este 0
// sau id-ul procesului curent este impar si elementul i este 1
if (((process_rank >> (i + 1)) % 2 == 0 && (process_rank >> j) % 2 == 0) ||
((process_rank >> (i + 1)) % 2 != 0 && (process_rank >> j) % 2 != 0)) {
CompareLow(j);
} else {
CompareHigh(j);
}
}
}
// Blocarea operarii pana cand toate procesele au terminat sortarea
MPI_Barrier(MPI_COMM_WORLD);

if (process_rank == MASTER) {
timer_end = MPI_Wtime();

printf("Afisarea elementelor dupa sortare (doar 10 pentru verificare rapida).\n");

11
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

// Afisare rezultate
for (i = 0; i < array_size; i++) {
if ((i % (array_size / OUTPUT_NUM)) == 0) {
printf("%d ",array[i]);
}
}
printf("\n\n");

printf("Timpul (Sec): %f\n", timer_end - timer_start);


}

// reseteaza memoria alocata dinamic


free(array);
MPI_Finalize();
return 0;
}

//functia de comparare
int ComparisonFunc(const void * a, const void * b) {
return ( * (int *)a - * (int *)b );
}

void CompareLow(int j) {
int i, min;

/* Trimite pe cel mai mare din lista si primeste pe cel mai mic */

12
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

// Trimite to vectorul la procese alaturate


// Face schimb cu procesul vecin al carui numar difera doar bitul j
int send_counter = 0;
int * buffer_send = malloc((array_size + 1) * sizeof(int));
MPI_Send(
&array[array_size - 1], // tot vectorul
1, // un singur element
MPI_INT, // INT
process_rank ^ (1 << j), // se calculeaza XOR pe procesele pereche cu 1 deplasat la stanga
//j pozitii;
0, // eticheta 0
MPI_COMM_WORLD
);
// Primirea minimului dintre elementele sortate
int recv_counter;
int * buffer_recieve = malloc((array_size + 1) * sizeof(int));
MPI_Recv(
&min, // buffer pt element
1, // 1 element
MPI_INT, // INT
process_rank ^ (1 << j), // se calc. XOR pe procesele pereche cu 1 deplasat la stanga j
//pozitii
0, // eticheta 0
MPI_COMM_WORLD,
MPI_STATUS_IGNORE // ignora informatii despre mesajul primit
);

13
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

// memorarea in bufferi a valorilor mai mari decat min


for (i = 0; i < array_size; i++) {
if (array[i] > min) {
buffer_send[send_counter + 1] = array[i];
send_counter++;
} else {
break; // Important, salveaza timp
}
}

buffer_send[0] = send_counter;

// trimiterea partitiei catre procesul invecinat


MPI_Send(
buffer_send, // trimite elementele mai mari decat min
send_counter, // nr elemente de trimis
MPI_INT, // INT
process_rank ^ (1 << j),
0, // tag 0
MPI_COMM_WORLD
);

// primirea informatiilor de la procesul invecinat


MPI_Recv(
buffer_recieve, // buffer pt mesaj
array_size, // dimensiunea vetorului

14
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019
MPI_INT, // INT
process_rank ^ (1 << j
0, // tag 0
MPI_COMM_WORLD,
MPI_STATUS_IGNORE
);

// memorarea valorilor mai mici decat maximul curent din bufferul primit de la procesul in
//vecinat
for (i = 1; i < buffer_recieve[0] + 1; i++) {
if (array[array_size - 1] < buffer_recieve[i]) {
// Store value from message
array[array_size - 1] = buffer_recieve[i];
} else {
break;
}
}

// Sortare secventiala quicksort


qsort(array, array_size, sizeof(int), ComparisonFunc);

// eliberarea memorie alocata dinamic


free(buffer_send);
free(buffer_recieve);

return;
}

15
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019

void CompareHigh(int j) {
int i, max;
/* Primeste pe cel mai mai mare din tot vectorul */
int recv_counter;
int * buffer_recieve = malloc((array_size + 1) * sizeof(int));
MPI_Recv(
&max, // valoarea maxima din buffer
1, // un element
MPI_INT, // INT
process_rank ^ (1 << j), // se calculeaza XOR pe procesele pereche cu 1 deplasat la stanga
//j pozitii;
0, // eticheta 0
MPI_COMM_WORLD,
MPI_STATUS_IGNORE
);
// Trimite minimul la vectorul procesului curent
int send_counter = 0;
int * buffer_send = malloc((array_size + 1) * sizeof(int));
MPI_Send(
&array[0], // trimite minim
1, // un item
MPI_INT, // INT
process_rank ^ (1 << j), // se calculeaza XOR pe procesele pereche cu 1 deplasat la stanga
//j pozitii;
0, // eticheta 0

16
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019
MPI_COMM_WORLD
);

// memoreaza intr-un buffer o lista de valori mai mici decat valoarea maxima for (i = 0; i <
array_size; i++) {
if (array[i] < max) {
buffer_send[send_counter + 1] = array[i];
send_counter++;
} else {
break;
}
}
//primirea de bloc-uri mai mari decat minimul din slave-ul pereche
MPI_Recv(
buffer_recieve, // buffer pt mesaj
array_size, // dimensiunea vectorului complet
MPI_INT, // INT
process_rank ^ (1 << j), se calculeaza XOR pe procesele pereche cu 1 deplasat la stanga
//j pozitii;
0, // eticheta 0
MPI_COMM_WORLD,
MPI_STATUS_IGNORE
);
recv_counter = buffer_recieve[0];

// trimite partitia catre slave-ul pereche


buffer_send[0] = send_counter;

17
Universitatea din Pitesti
Facultatea de Electronica, Comunicatii si Calculatoare
Student: Coada Marius-Cristian
An,grupa,subgrupa: C311
An universitar: 2018-2019
MPI_Send(
buffer_send, // toate elementele mai mici decat max
send_counter, // nr elemente mai mici decat max
MPI_INT, // INT
process_rank ^ (1 << j), se calculeaza XOR pe procesele pereche cu 1 deplasat la stanga
//j pozitii;
0, // eticheta 0
MPI_COMM_WORLD
);
//primirea buffer-ului cu valori mai mari decat minimul curent de la procesul pereche for (i = 1;
i < recv_counter + 1; i++) {
if (buffer_recieve[i] > array[0]) {
// memorare valoare
array[0] = buffer_recieve[i];
} else {
break;
}
}
// Sortare seventiala quicksort
qsort(array, array_size, sizeof(int), ComparisonFunc);

// eliberarea zonelor de memorie alocate dinamic


free(buffer_send);
free(buffer_recieve);
return;
}

18

S-ar putea să vă placă și