2014-01-12 4 views
0

저는 MPI 프로그래밍을 시작하고 OpenMPI를 사용하여 간단한 분산 qsort를 만들기로 결정했습니다. 나에게 내가 MPI_Scatterv를 사용하는 것을 시도하고 정렬 할 배열의 일부 그러나 다음 코드 세그먼테이션 폴트 (segfault)를 배포하려면 : 나는 Scatterv 사용에 대한 갈 것이라고 어떻게MPI_Scatterv segfault

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

#define ARRAY_SIZE 26 
#define BUFFER_SIZE 2048 

int main(int argc, char** argv) { 
    int my_rank, nr_procs; 

    int* data_in, *data_out; 
    int* sizes; 
    int* offsets; 

    srand(time(0)); 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &nr_procs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); 

    // everybody generates the control tables 
    int nr_workers = nr_procs-1; 
    sizes = malloc(sizeof(int)*nr_workers); 
    offsets = malloc(sizeof(int)*nr_workers); 

    int nr_elems = ARRAY_SIZE/nr_workers; 

    // basic distribution 
    for (int i = 0; i < nr_workers; ++i) { 
     sizes[i] = nr_elems; 
    } 
    // distribute the remainder 
    int left = ARRAY_SIZE%nr_workers; 
    int curr_worker = 0; 
    while (left) { 
     ++sizes[curr_worker]; 
     curr_worker = (++curr_worker)%nr_workers; 
     --left; 
    } 
    // offsets 
    int curr_offset = 0; 
    for (int i = 0; i < nr_workers; ++i) { 
     offsets[i] = curr_offset; 
     curr_offset += sizes[i]; 
    } 


    if (my_rank == 0) { 
     // root 
     data_in = malloc(sizeof(int)*ARRAY_SIZE); 
     data_out = malloc(sizeof(int)*ARRAY_SIZE); 
     for (int i = 0; i < ARRAY_SIZE; ++i) { 
      data_in[i] = rand(); 
     } 

     for (int i = 0; i < nr_workers; ++i) { 
      printf("%d at %d\n", sizes[i], offsets[i]); 
     } 

     MPI_Scatterv (data_in, sizes, offsets, MPI_INT, data_out, ARRAY_SIZE, MPI_INT, 0, MPI_COMM_WORLD); 


    } else { 
     // worker 
     printf("%d has %d elements!\n",my_rank, sizes[my_rank-1]); 
     // alloc the input buffer 
     data_in = malloc(sizeof(int)*sizes[my_rank-1]); 

     MPI_Scatterv(NULL, NULL, NULL, MPI_INT, data_in, sizes[my_rank-1], MPI_INT, 0, MPI_COMM_WORLD); 

     printf("%d got:\n", my_rank); 
     for (int i = 0; i < sizes[my_rank-1]; ++i) { 
      printf("%d ", data_in[i]); 
     } 
     printf("\n"); 
    } 

    MPI_Finalize(); 
    return 0; 
} 

를? 작업자 코드 내부에서 입력 버퍼를 할당하는 데 문제가 있습니까?

답변

1

코드에서 일부 기능을 변경했습니다.

MPI_Scatter()은 자신을 포함하여 모든 프로세서로 데이터를 보냅니다. 귀하의 프로그램에 따르면 프로세서 0은 ARRAY_SIZE 정수를 기대하지만 sizes[0]은 훨씬 더 작습니다. 다른이 과정이 다른 문제가 있습니다 MPI_Scatter가 sizes[my_rank-1] 예상됩니다 sizes[my_rank] 정수를 보내지 만합니다 ... 여기

은 0 그러므로 내가 nr_workers에 1을 추가 포함, 모든 프로세서 0 ~ data_in을 산란 코드입니다 :

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

#define ARRAY_SIZE 26 
#define BUFFER_SIZE 2048 

int main(int argc, char** argv) { 
    int my_rank, nr_procs; 

    int* data_in, *data_out; 
    int* sizes; 
    int* offsets; 

    srand(time(0)); 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &nr_procs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); 

    // everybody generates the control tables 
    int nr_workers = nr_procs; 
    sizes = malloc(sizeof(int)*nr_workers); 
    offsets = malloc(sizeof(int)*nr_workers); 

    int nr_elems = ARRAY_SIZE/nr_workers; 

    // basic distribution 
    for (int i = 0; i < nr_workers; ++i) { 
     sizes[i] = nr_elems; 
    } 
    // distribute the remainder 
    int left = ARRAY_SIZE%nr_workers; 
    int curr_worker = 0; 
    while (left) { 
     ++sizes[curr_worker]; 
     curr_worker = (++curr_worker)%nr_workers; 
     --left; 
    } 
    // offsets 
    int curr_offset = 0; 
    for (int i = 0; i < nr_workers; ++i) { 
     offsets[i] = curr_offset; 
     curr_offset += sizes[i]; 
    } 

    if (my_rank == 0) { 
     // root 
     data_in = malloc(sizeof(int)*ARRAY_SIZE); 

     for (int i = 0; i < ARRAY_SIZE; ++i) { 
      data_in[i] = rand(); 
      printf("%d %d \n",i,data_in[i]); 
     } 

     for (int i = 0; i < nr_workers; ++i) { 
      printf("%d at %d\n", sizes[i], offsets[i]); 
     } 


    } else { 
     printf("%d has %d elements!\n",my_rank, sizes[my_rank]); 
    } 
    data_out = malloc(sizeof(int)*sizes[my_rank]); 

    MPI_Scatterv (data_in, sizes, offsets, MPI_INT, data_out, sizes[my_rank], MPI_INT, 0, MPI_COMM_WORLD); 

    printf("%d got:\n", my_rank); 
    for (int i = 0; i < sizes[my_rank]; ++i) { 
     printf("%d ", data_out[i]); 
    } 
    printf("\n"); 
    free(data_out); 
    if(my_rank==0){ 
     free(data_in); 
    } 
    MPI_Finalize(); 
    return 0; 
} 

대하여 메모리 관리, 및 data_indata_out은 코드의 끝에서 해방한다.

원하는대로 할 수 있습니까? qsort와 행운을 비네! 나는 당신이 MPI를 사용하여 정수를 분류하는 첫번째 사람이 아니라고 생각합니다. parallel sort using mpi을 참조하십시오. 0 processus에서 임의의 숫자를 생성 한 다음이를 분산시키는 방법은 올바른 방법입니다. 나는 당신이 그의 통신 TD_Trier() 함수에 의해 interrested 것 같아요. 심지어

안녕 ... 당신이 qsort(...)에 대한 tri_fusion(T, 0, size - 1);을 변경하는 경우,

프랜시스

+0

당신에게 설명과 유용한 팁을 주셔서 대단히 감사합니다! 초보자로서 저는 MPI에 관한 문서가 꽤 부족하다는 것을 알고 있습니다. 많은 참고 자료가 있지만, 대부분의 자료는 잘 설명되어 있지 않습니다. 나에게도 루트 프로세스가 데이터를 보내지는 않습니다 (추후에 완벽한 의미를 가짐). 슬프게도 나는 너무 새롭기 때문에 당신의 기여에 대해 당신을 대신 할 수는 없다 : ( –

+0

@SidCasey : 아무런 문제 없다 : 나의 대답을 받아 들였고 더 요구할 수 없다! – francis

+1

나는 Deino가 아니다. 하지만 MPI에 대한 그의 참조 페이지가 마음에 든다. http://mpi.deino.net/mpi_functions/MPI_Scatter.html –