MPI calloc ทำให้เกิดข้อผิดพลาดในการแบ่งส่วน

ฉันเขียนโปรแกรมเพื่อค้นหาผลรวมขององค์ประกอบอาร์เรย์ด้วย MPI ทั้งรูทและผู้ปฏิบัติงานจะค้นหาผลรวมของส่วนและผู้ปฏิบัติงานจะส่งผลรวมบางส่วนไปยังรูทในตอนท้าย เมื่อฉันลองใช้อาเรย์ขนาดคงที่ก็ไม่มีปัญหาใดๆ แต่มันทำให้เกิดข้อผิดพลาดในการแบ่งส่วนหากฉันใช้ calloc ซอร์สโค้ดได้รับด้านล่าง:

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define tag1 1 /* send from root to workers */
#define tag2 2 /* send from workers to root */
#define root 0
#define n_data 12

int main(int argc, char *argv[]) 
{ 
    int total_sum, partial_sum;
    int my_id, i, n_procs, n_portion;

    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);
    n_portion=n_data/n_procs;

    int *array = (int *)calloc(n_data, sizeof(int));
    int *local  = (int *)calloc(n_portion, sizeof(int));

    if(my_id == root) { 

        /* initialize array */
        for(i = 0; i < n_data; i++) 
            array[i]=i;

        /* send a portion of the array to each worker */
        for(i= 1; i < n_procs; i++) 
            MPI_Send( &array[i*n_portion], n_portion, MPI_INT,i, tag1, MPI_COMM_WORLD); 

        /* calculate the sum of my portion */
        for(i = 0; i < n_portion; i++)
            total_sum += array[i];

        /* collect the partial sums from workers */
        for(i= 1; i < n_procs; i++) {
            MPI_Recv( &partial_sum, 1, MPI_INT, MPI_ANY_SOURCE,tag2, MPI_COMM_WORLD, &status);
            total_sum += partial_sum; 
        }

        printf("The total sum is: %d\n", total_sum);
    }
    else { /* I am a worker, receive data from root */

        MPI_Recv( &local, n_portion, MPI_INT, root, tag1, MPI_COMM_WORLD, &status);

        /* Calculate the sum of my portion of the array */
        partial_sum = 0;
        for(i = 0; i < n_portion; i++)
            partial_sum += local[i];

        /* send my partial sum to the root */
        MPI_Send( &partial_sum, 1, MPI_INT, root, tag2, MPI_COMM_WORLD);
    }

    MPI_Finalize(); 
    return 0;
}

ข้อผิดพลาดที่ฉันทำคือ:

-bash-4.1$ mpirun -np 3 distApprox
--------------------------------------------------------------------------
mpirun noticed that process rank 2 with PID 110834 on node levrek1 exited on signal 11 (Segmentation fault).
--------------------------------------------------------------------------

ขอบคุณที่ช่วยเหลือ.


person smtnkc    schedule 16.12.2015    source แหล่งที่มา
comment
ค่าของ n_portion คืออะไร?   -  person PaulMcKenzie    schedule 16.12.2015
comment
คุณได้พยายามแก้ไขโค้ดแล้ว ซึ่งบรรทัดใดที่ได้รับข้อผิดพลาดในการแบ่งส่วน well calloc ส่งคืนตัวชี้ null หากไม่สามารถจัดสรรโค้ดได้   -  person rahul.deshmukhpatil    schedule 16.12.2015
comment
@PaulMcKenzie ฉันรัน 3 กระบวนการและฉันมี 12 องค์ประกอบในอาร์เรย์ ดังนั้น n_portion = 4.   -  person smtnkc    schedule 16.12.2015
comment
@JoachimPileborg แต่มันควรจะเป็นเช่นนั้น เพราะฉันใช้รูทเป็นคนทำงานด้วย ถ้า n_procs เป็น 2 รูท จะคำนวณครึ่งหนึ่งของอาร์เรย์ และ worker1 จะถูกคำนวณอีกครึ่งหนึ่ง   -  person smtnkc    schedule 16.12.2015
comment
@samet - คุณสมมุติว่ามันจะเป็น 4 หรือคุณยืนยันแล้วว่า เป็น 4 หรือไม่? รหัสของคุณไม่มีการตรวจสอบข้อผิดพลาด ซึ่งเป็นสาเหตุว่าทำไมจึงยังไม่ชัดเจนว่าค่านั้นเป็น 4 จริง ๆ หรือไม่ สิ่งที่เรามีคือการเรียก calloc พร้อมตัวแปรที่เราไม่รู้ว่ามันคืออะไร แล้วฮาร์ดโค้ด 4 แทนที่จะใช้ตัวแปรล่ะ หากคุณทำเช่นนั้น คุณจะยังมีปัญหาอยู่หรือไม่?   -  person PaulMcKenzie    schedule 16.12.2015
comment
คุณไม่ได้ตรวจสอบผลลัพธ์ของ calloc() บางทีมันอาจจะล้มเหลว   -  person John Zwinck    schedule 16.12.2015
comment
หมายเหตุด้านข้าง: คุณลืมเริ่มต้น total sum ข้อเท็จจริงนี้ทำให้ฉันเชื่อว่าคุณต้องเพิ่มระดับการเตือน เพิ่ม -wall ลงในบรรทัดคำสั่งคอมไพเลอร์ของคุณ (สมมติว่าคุณใช้ gcc)   -  person Klas Lindbäck    schedule 16.12.2015
comment
ขอบคุณสำหรับความคิดเห็น ฉันมีปัญหากับเซิร์ฟเวอร์ mpi ในตอนนี้ ฉันจะพยายามทั้งหมดและให้ข้อเสนอแนะภายในไม่กี่นาที   -  person smtnkc    schedule 16.12.2015
comment
มันไม่ควรเป็นเพียง local แทนที่จะเป็น &local ในการเรียก MPI_Recv ใช่ไหม   -  person Martin Zabel    schedule 16.12.2015
comment
@PaulMcKenzie มีปัญหาเดียวกันเมื่อฉันฮาร์ดโค้ด n_portion เป็น 4 ดังนั้นฉันจึงเริ่มต้น total_sum = 0 ตามที่ Klas ชี้และเปลี่ยน &local เป็น local ตามที่ Martin ชี้ มันได้ผล! ขอบคุณ.   -  person smtnkc    schedule 17.12.2015


คำตอบ (1)


ฉันจะบอกว่าปัญหาอยู่ที่ MPI_Recv ทางฝั่งผู้ปฏิบัติงาน คุณควรใช้ 'local' แทน '&local' เป็นบัฟเฟอร์ MPI คาดว่า "ที่อยู่เริ่มต้นของบัฟเฟอร์การรับ" (ดูมาตรฐาน MPI) ซึ่งในกรณีของอาร์เรย์ไดนามิกก็คือตัวแปรอาร์เรย์นั่นเอง

MPI_Recv( local, n_portion, MPI_INT, root, tag1, MPI_COMM_WORLD, &status);

คุณอาจต้องการกำหนดค่าเริ่มต้น 'total_sum' เป็น 0 บนรูท จากนั้นโค้ดของคุณควรทำงาน

แก้ไข: เพิ่งเห็นว่า Martin Zabel ชี้ให้เห็นสิ่งนี้ในความคิดเห็นแล้ว

person Johannes    schedule 16.12.2015
comment
ขอบคุณ! โซลูชั่นที่สมบูรณ์แบบ - person smtnkc; 17.12.2015