2016-12-09 5 views
2

Я ухожу. Это самая неприятная вещь, которую я когда-либо делал. Даже нединамический массив int вызывает segfault. Но если я объявляю его как массив float/char, он работает нормально.Ошибка сегментации при распределении второго массива


Update: Если я удалить строку MPI_Scatter(A[0], N, MPI_INT, A_row, N, MPI_INT, 0, MPI_COMM_WORLD); она отлично работает. Проблема в том, что мне это нужно ...


Я работаю над программой, но у меня есть странная проблема.

Следующий код работает отлично (если предположить, что N кратно р):

#include <stdio.h> 
#include <stdlib.h> 
#include "mpi.h" 


void main(int argc, char** argv) 
{ 
    int my_rank, p, N, **A, *diagonals, *A_row; 
    MPI_Status status; 

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

    if (my_rank == 0) { 

     N = 4; 
     int *mem = malloc(N * N * sizeof(int)); 
     A = malloc(N * sizeof(int*)); 
     for(int i = 0; i < N; i++) 
      A[i] = mem + N*i;  

    } 
    MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    A_row = malloc (N * sizeof(int)); 

    MPI_Scatter(A[0], N, MPI_INT, A_row, N, MPI_INT, 0, MPI_COMM_WORLD); 

    MPI_Finalize(); 
} 

Однако мне нужно выделить еще один массив (диагоналей), как это:

#include <stdio.h> 
#include <stdlib.h> 
#include "mpi.h" 


void main(int argc, char** argv) 
{ 
    int my_rank, p, N, **A, *diagonals, *A_row; 
    MPI_Status status; 

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

    if (my_rank == 0) { 

     N = 4; 
     int *mem = malloc(N * N * sizeof(int)); 
     A = malloc(N * sizeof(int*)); 
     for(int i = 0; i < N; i++) 
      A[i] = mem + N*i; 

     diagonals = malloc (N * sizeof(int));  
    } 
    MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    A_row = malloc (N * sizeof(int)); 

    MPI_Scatter(A[0], N, MPI_INT, A_row, N, MPI_INT, 0, MPI_COMM_WORLD); 

    MPI_Finalize(); 
} 

Я получаю эту ошибку сегментации (если это помогает на всех):

[teo-VirtualBox:02582] *** Process received signal *** 
[teo-VirtualBox:02582] Signal: Segmentation fault (11) 
[teo-VirtualBox:02582] Signal code: Address not mapped (1) 
[teo-VirtualBox:02582] Failing at address: 0x1 
[teo-VirtualBox:02582] [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x113d0)[0x7faecc8d23d0] 
[teo-VirtualBox:02582] [ 1] a[0x400c85] 
[teo-VirtualBox:02582] [ 2] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7faecc511830] 
[teo-VirtualBox:02582] [ 3] a[0x4009a9] 
[teo-VirtualBox:02582] *** End of error message *** 

Я пропустил что-то очевидное?

Кстати, я не использую free() или ничего не делаю, потому что это не полный код. Это просто файл, который я создал для тестирования.

+2

Для будущего, загрузите программу с помощью GDB, и он расскажет вам, что линия сегментного неисправного, и вы можете проверить значение некоторых переменные. –

+0

@SanchkeDellowar Я не знаком с gdb. Я попробовал 'mpiexec -np 4 a.out -gdb', но это не имеет никакого значения в сообщении об ошибке. –

+0

@TeoAlivanoglou Не могли бы вы попытаться уничтожить свой код до минимального проверяемого примера, то есть вынуть все (в основном, материал mpi), который вам не нужен, чтобы мы могли попробовать запустить его самостоятельно? – gowrath

ответ

1

Честно говоря, я не могу воспроизвести:

linux21:/home/users/grad1459/Desktop/parallel>mpiexec -np 4 a.out 
linux21:/home/users/grad1459/Desktop/parallel>mpicc -Wall -std=c99 main.c 
main.c: In function ‘main’: 
main.c:9:15: warning: unused variable ‘status’ [-Wunused-variable] 
main.c:8:29: warning: variable ‘diagonals’ set but not used [-Wunused-but-set-variable] 
linux21:/home/users/grad1459/Desktop/parallel>mpiexec -np 4 a.out 
ALL OK 
ALL OK 
ALL OK 
ALL OK 
linux21:/home/users/grad1459/Desktop/parallel> 

с очень похожим кодом на ваш:

#include <stdio.h> 
#include <stdlib.h> 
#include "mpi.h" 


int main(int argc, char** argv) 
{ 
    int my_rank, p, N, **A, *diagonals, *A_row; 
    MPI_Status status; 

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

    if (my_rank == 0) { 

     N = 4; 
     int *mem = malloc(N * N * sizeof(int)); 
     A = malloc(N * sizeof(int*)); 
     for(int i = 0; i < N; i++) 
      A[i] = mem + N*i; 

     diagonals = malloc (N * sizeof(int)); 
    } 
    MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    A_row = malloc (N * sizeof(int)); 

    MPI_Scatter(A[0], N, MPI_INT, A_row, N, MPI_INT, 0, MPI_COMM_WORLD); 

    MPI_Finalize(); 
    printf("ALL OK\n"); 
    return 0; 
} 

В результате, я думаю, что ваш VirtualBox имеет некоторые ограничения памяти и ваш malloc() терпит неудачу , проверьте его возвращаемое значение, чтобы убедиться, что это не NULL, вот так: How detect malloc failure?

Это моя версия:

linux21:/home/users/grad1459/Desktop/parallel>mpiexec --version 
HYDRA build details: 
    Version:         3.1.3 
    Release Date:       Wed Oct 8 09:37:19 CDT 2014 
    CC:        gcc  
    CXX:        g++  
    F77:        gfortran 
    F90:        gfortran 
    Configure options:      '--disable-option-checking' '--prefix=/usr/local/mpich3' '--cache-file=/dev/null' '--srcdir=.' 'CC=gcc' 'CFLAGS= -O2' 'LDFLAGS= ' 'LIBS=-lpthread ' 'CPPFLAGS= -I/usr/local/USB/mpich-3.1.3/src/mpl/include -I/usr/local/USB/mpich-3.1.3/src/mpl/include -I/usr/local/USB/mpich-3.1.3/src/openpa/src -I/usr/local/USB/mpich-3.1.3/src/openpa/src -D_REENTRANT -I/usr/local/USB/mpich-3.1.3/src/mpi/romio/include' 
    Process Manager:       pmi 
    Launchers available:      ssh rsh fork slurm ll lsf sge manual persist 
    Topology libraries available:   hwloc 
    Resource management kernels available: user slurm ll lsf sge pbs cobalt 
    Checkpointing libraries available:  
    Demux engines available:     poll select 

Может быть, проблема в том, что вы не free() свою память? Вы попробовали это?

В общем случае при использовании попробуйте выделить двумерный динамический массив в смежных ячейках памяти (чтобы MPI мог свободно использовать свой шаг и т. Д.). В общем, вы можете сделать это с помощью следующих функций:

int** allocate2D(int** A, const int N, const int M) { 
    int i; 
    int *t0; 

    A = malloc(M * sizeof (int*)); /* Allocating pointers */ 
    t0 = malloc(N * M * sizeof (int)); /* Allocating data */ 
    for (i = 0; i < M; i++) 
     A[i] = t0 + i * (N); 

    return A; 
} 

void free2Darray(int** p, const int N) { 
    free(p[0]); 
    free(p); 
} 

как я объясняю в 2D dynamic array in continuous memory locations (C) .


Unrelated к вашей ошибке во время выполнения: Why do we need to use `int main` and not `void main` in C++?

+0

Разве это не то же самое, что я сделал? Просто 'mem' вместо' t0'. Кроме того, спасибо за страницу int vs void. Кроме того, что я могу освободить, не испорчая мои данные? Эта программа, очевидно, делает больше вещей, чем это. –

+0

Oops @TeoAlivanoglou вы делаете почти то же самое, но с кодами строк, замененных, извините. Ну, вы обычно 'free()' свою память, когда вам это больше не нужно, другими словами, когда вам не нужны данные. Теперь вы можете увидеть, работает ли минимальный пример. Я пробовал на машинах своего университета, и он отлично работал, даже не освобождая память! – gsamaras

+0

Ничего себе. Я даже скопировал ваш код, чтобы убедиться, что он на 100% тот же. Я все еще получаю ошибку. Есть ли шанс, что мои mpi или gcc будут сломаны? Или, может быть, ограничения VirtualBox? –

Смежные вопросы