Я все еще новичок, когда дело доходит до MPI, и я пытаюсь определить и тип MPI, чтобы соответствовать пользовательской структуре, которую я написал.Идея, лежащая в основе этого, заключается в том, чтобы список студентов был отправлен в несколько процессов, каждый из которых использовал его для поиска, скажем, определенного.Я специально инициализировал первый элемент в списке, чтобы я мог проверить, работает ли программа.Функция поиска реализована, но не используется.
Проблемы:
- Я хотел убедиться, что мои данные правильно передаются процессам, поэтому я хотел напечатать их локальный список (локальный).Я обнаружил, что после первых нескольких записей все запуталось, и я не могу понять, почему.
- Есть ли способ иметь указатели вместо массивов символов в стороне структуры?Насколько я прочитал, нет никакого способа сделать это, потому что пространство памяти не используется совместно.это правильно?
- Есть ли лучший способ инициализировать массив символов из указателя?Я думаю, что это использует много памяти.
Некоторые части кода были прокомментированы, такие как принимающая часть процессов, для целей отладки.Я скомпилировал исходный код, используя mpicc students.c -Wall -Wextra -g
, и выполнил его, используя mpiexec -n 4 ./a.out
.
Код:
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NELEM 25
#define MAX_STR_LENGTH 30
#define MAX_FNAME_LENGTH 10
#define MAX_LNAME_LENGTH 10
#define MAX_YEAR_ID_LENTGH 3
#define MAX_CNP_LENGTH 13
#define MAX_YEARS 6
#define TAG 1
#define MASTER 0
#define TRUE 1
#define FALSE 0
#define FNAME_LABEL "First name"
#define LNAME_LABEL "Last name"
#define CNP_LABEL "CNP"
#define STUDIES_LABEL "Studies"
#define YEAR_LABEL "Year"
typedef struct
{
char firstName[MAX_FNAME_LENGTH];
char lastName[MAX_LNAME_LENGTH];
char cnp[MAX_CNP_LENGTH];
char studies[MAX_YEAR_ID_LENTGH];
int year;
} Student;
void receive(MPI_Datatype type, int rank);
void send_data(Student data[], MPI_Datatype type, int num_procs);
void initialize(Student data[]);
char *rand_string(char *str, size_t size);
char *rand_string_alloc(size_t size);
int rand_year();
void initialize_student(Student *stud);
void fill_field(char data[], char *fill, int size, int max_size);
void print_field(char data[], int size, char *field_label);
void print_stud(Student stud);
int is_a_match(char lvalue[], char *rvalue);
Student *search_stud(char *cnp, Student students[], int list_size);
void initialize_custom_student(Student *stud);
void print_list(Student students[], int size, int rank);
int main(int argc, char **argv)
{
srand(time(NULL));
int num_procs, rank;
Student to_send[NELEM];
MPI_Datatype studentType, oldtypes[2];
int blockcounts[2];
/* MPI_Aint type used to be consistent with syntax of */
/* MPI_Type_extent routine */
MPI_Aint offsets[2], extent;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
/* Setup description of the 4 MPI_FLOAT fields x, y, z, velocity */
offsets[0] = 0;
oldtypes[0] = MPI_CHAR;
blockcounts[0] = 4;
/* Setup description of the 2 MPI_INT fields n, type */
/* Need to first figure offset by getting size of MPI_FLOAT */
MPI_Type_extent(MPI_CHAR, &extent);
offsets[1] = 4 * extent;
oldtypes[1] = MPI_INT;
blockcounts[1] = 1;
/* Now define structured type and commit it */
MPI_Type_struct(2, blockcounts, offsets, oldtypes, &studentType);
MPI_Type_commit(&studentType);
/* Initialize the particle array and then to_send it to each task */
if (rank == MASTER)
{
initialize(to_send);
send_data(to_send, studentType, num_procs);
// print_list(to_send, NELEM, rank);
}
else
{
// receive(studentType, rank);
}
//sanity-check printing
if (rank == num_procs - 1)
{
receive(studentType, rank);
}
MPI_Type_free(&studentType);
MPI_Finalize();
}
void receive(MPI_Datatype type, int rank)
{
// printf("Process %d is awaiting data....!\n", rank);
Student local[NELEM];
MPI_Status status;
MPI_Recv(local, NELEM, type, MASTER, TAG, MPI_COMM_WORLD, &status);
print_list(local, NELEM, rank);
// printf("[OK]:Proccess %d has finished receiving all the data!\n", rank);
}
void send_data(Student data[], MPI_Datatype type, int num_procs)
{
// printf("Sending data....!\n");
for (int i = 1; i < num_procs; i++)
{
MPI_Send(data, NELEM, type, i, TAG, MPI_COMM_WORLD);
}
// printf("[OK]:All data was sent!\n");
}
void initialize(Student data[])
{
initialize_custom_student(&data[0]);
printf("Initializing data....!\n");
for (int i = 1; i < NELEM; i++)
{
initialize_student(&data[i]);
}
printf("[OK]:Data initialized!\n");
}
void initialize_custom_student(Student *stud)
{
char *fName = "Some";
int fNameSize = 5;
char *lName = "Name";
int lNameSize = 7;
char *cnp = "1234";
int cnpSize = 4;
char *studies = "CS";
int studiesSize = 2;
fill_field(stud->firstName, fName, fNameSize, MAX_FNAME_LENGTH);
fill_field(stud->lastName, lName, lNameSize, MAX_LNAME_LENGTH);
fill_field(stud->cnp, cnp, cnpSize, MAX_CNP_LENGTH);
fill_field(stud->studies, studies, studiesSize, MAX_YEAR_ID_LENTGH);
stud->year = 4;
}
void initialize_student(Student *stud)
{
int fNameSize = rand() % MAX_FNAME_LENGTH;
char *firstname = rand_string_alloc(fNameSize);
int lNameSize = rand() % MAX_LNAME_LENGTH;
char *lastName = rand_string_alloc(MAX_LNAME_LENGTH);
int cnpSize = rand() % MAX_CNP_LENGTH;
char *CNP = rand_string_alloc(MAX_CNP_LENGTH);
int studiesSize = rand() % MAX_YEAR_ID_LENTGH;
char *studies = rand_string_alloc(MAX_YEAR_ID_LENTGH);
fill_field(stud->firstName, firstname, fNameSize, MAX_FNAME_LENGTH);
fill_field(stud->lastName, lastName, lNameSize, MAX_LNAME_LENGTH);
fill_field(stud->cnp, CNP, cnpSize, MAX_CNP_LENGTH);
fill_field(stud->studies, studies, studiesSize, MAX_YEAR_ID_LENTGH);
stud->year = rand_year();
free(firstname);
free(lastName);
free(CNP);
free(studies);
}
void fill_field(char data[], char *fill, int size, int max_size)
{
for (int i = 0; i < size; i++)
{
data[i] = fill[i];
}
for (int i = size; i < max_size; i++)
{
data[i] = '*';
}
}
void print_field(char data[], int size, char *field_label)
{
printf(" %s: ", field_label);
for (int i = 0; i < size; i++)
{
char character = data[i];
if (character == '*')
{
break;
}
printf("%c", character);
}
printf("\n");
}
char *rand_string(char *str, size_t size)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
if (size)
{
--size;
for (size_t n = 0; n < size; n++)
{
int key = rand() % (int)(sizeof charset - 1);
str[n] = charset[key];
}
str[size] = '\0';
}
return str;
}
char *rand_string_alloc(size_t size)
{
char *s = malloc(size + 1);
if (s)
{
rand_string(s, size);
}
return s;
}
int rand_year()
{
return rand() % MAX_YEARS;
}
void print_stud(Student stud)
{
print_field(stud.firstName, MAX_FNAME_LENGTH, FNAME_LABEL);
print_field(stud.lastName, MAX_LNAME_LENGTH, LNAME_LABEL);
print_field(stud.cnp, MAX_CNP_LENGTH, CNP_LABEL);
print_field(stud.studies, MAX_YEAR_ID_LENTGH, STUDIES_LABEL);
}
Student *search_stud(char *cnp, Student students[], int list_size)
{
Student *current = NULL;
for (int i = 0; i < list_size; i++)
{
*current = students[i];
if (is_a_match(current->cnp, cnp))
{
return current;
}
}
return NULL;
}
int is_a_match(char lvalue[], char *rvalue)
{
for (int i = 0; i < MAX_CNP_LENGTH; i++)
{
char left = lvalue[i];
char right = rvalue[i];
if (left == '0' || right == '0' || left != right)
{
return FALSE;
}
}
return TRUE;
}
void print_list(Student students[], int size, int rank)
{
for (int i = 0; i < size; i++)
{
print_stud(students[i]);
printf("\n");
}
}
Спасибо!