Untitled

mail@pastecode.io avatar
unknown
c_cpp
7 months ago
5.5 kB
1
Indexable
Never
התרגיל : 

נתונים המערכים D ,C ,B ,A הידועים לתהליכים 3P 2,P 1,P 0,P בהתאמה. המערכים בגודל N כל אחד 
ומכילים מספרים שלמים. מטרת התוכנית היא להדפיס את כל האיברים של מערך A ושל מערך B שעבורם 
מתקיימים התנאים: 
f(A[i]) > C[i]
f(B[i]) < D[i]
הדרישות: 
• יש לכתוב תכנית מקבילית יעילה המשתמשת ב- MPI וב- OpenMP . 
• ברשותכם שני מחשבים עם ארבע ליבות כל אחד. 
• כל ההדפס ות יבוצעו על תהליך עם ראנק (rank (.0 
• יש להשתמש בפונקציות Gather_MPI ו-Scatter_MPI בכל מקום מתאים.
• אפשר להניח שהמספר N מתחלק ב.8- 
• הפונקציה f מקבלת פרמטר מסוג int ומחזירה מספר double. הפונקציה נחשבת כמאוד כבדה, אין צורך 
ליישם אותה. 
• אין צורך לאתחל את המערכים D ,C ,B ,A.

אני עשיתי פתרון ל2 מחשבים ו4 ליבות כל אחד.
ובלי הפונקציות שביקשו..

פתרון שלי : 

#include <mpi.h>
#include <stdio.h>
#include <omp.h>
#include <math.h>
#include <stdlib.h>

void print_elements(int *A, int *B, int *result_A, int *result_B, int N) {
    for (inti = 0; i < N; i++) {
        if (result_A[i])
            printf("%d ", A[i]);
        if (result_B[i])
            printf("%d ", B[i]);
    }
}

double f(int x) {
    double res = 0.0;
    for (int i = 0; i < 10; i++) {
        res += sin(x * i) * cos(x * i) / (i + 1);
    }
    return res;
}
int readA(**A);
int readB(**B);
int readC(**C);
int readD(**D);
int main(int argc, char **argv) {
    int rank, size, N;
    int *A, *B, *C, *D, *result_A, *result_B;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (rank == 0) {
        N = readA(&A); // assume he reads the array and return the size ! 
        readC(&C); // assume he reads the array and return the size ! 
    }
    if (rank == 1) {
        N = readB(&B);// assume he reads the array and return the size ! 
         readD(&D);// assume he reads the array and return the size ! 
    }

    if (rank == 0) {
        result_A = calloc(N, sizeof(int)); //rank 0 will calc by him self
        result_B = malloc(N * sizeof(int));//will be filled from rank 1
        
        // Compute result_A
        #pragma omp parallel for num_threads(4)
        for (int i = 0; i < N; i++) {
            if (f(A[i]) > C[i])
                result_A[i] = 1;
        }
        
        MPI_Recv(result_B, N, MPI_INT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        
        print_elements(rank, A, B, result_A, result_B, N);
        
    } else {
        result_B = calloc(N, sizeof(int);
        
        // Compute result_B
        #pragma omp parallel for num_threads(4)
        for (int i = 0; i < N; i++) {
            if (f(B[i]) < D[i])
                result_B[i] = 1;
        }

        MPI_Send(result_B, N, MPI_INT, 0, 0, MPI_COMM_WORLD);
    }

    MPI_Finalize();
    
    return 0;
}

// פתרון שלהם

int rank, size, i, j, nproc;
int data[2];
int A[N], B[N], C[N], D[N];
int part = N/4;
// מחלקים לכל אחד רבע מערך לחישוב
int a[N/4], b[N/4], c[N/4], d[N/4], result_a[N/4], result_b[N/4];
int count, count_a, count_b;
MPI_Status status;
int *arr;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
int numOfElements;
if (rank == 0) {
numOfElements = N;
for (i = 0; i < N; i++)
A[i] = i;
B[i] = i;
C[i] = i;
D[i] = i;
}
// מפזרים לכל תהליך מתוך ה4 רבע מכל מערך שעליו הוא יעבוד

MPI_Scatter(A, PART, MPI_INT, a, PART, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(B, PART, MPI_INT, b, PART, MPI_INT, 1, MPI_COMM_WORLD);
MPI_Scatter(C, PART, MPI_INT, c, PART, MPI_INT, 2, MPI_COMM_WORLD);
MPI_Scatter(D, PART, MPI_INT, d, PART, MPI_INT, 3, MPI_COMM_WORLD);

count_a = 0;
count_b = 0;
// אינדקסים לשליטה על הקמת המערך החדש עם הערכים שצריך להדפיס
#pragma omp parallel for
for (i = 0; i < PART; i++) {
if (f(a[i]) > c[i])
    result_a[count_a++] = a[i];

if (f(b[i]) < d[i])
    result_b[count_b++] = b[i];
}
if (rank != 0) {
    // נעביר את המידע שצברנו וכאן זה מחזיר באמצעות דאבל סוג של קאסטינג
MPI_Send(result_a, count_a, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
MPI_Send(result_b, count_b, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
printf("rank = %d\n", rank);
}
else {//rank 0 יעשה את זה
    for (i = 1; i < nproc; i++) {
        // דורסים מערך קיים כדי לנצל שהוא קיים וניקח ממנו רק את החלקים שנרצה להדפסה בעזרת ה גט קאונט הזה.
    MPI_Recv(A, PART, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
    MPI_Get_count(&status, MPI_DOUBLE, &count);
    printf("A\n");
    for (j = 0; j < count; j++)
    printf("%e\n", A[j]);
        }
for (i = 1; i < nproc; i++) {
    MPI_Recv(B, PART, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
    MPI_Get_count(&status, MPI_DOUBLE, &count);
    printf("B\n");
    for (j = 0; j < count; j++)
    printf("%e\n", B[j]);
    }
}
Leave a Comment