• Thứ Ba, 06/01/2004 11:53 (GMT+7)

    Lập trình song song trên Linux

    Hiện nay tốc độ máy tính đã có cải thiện đáng kể, tuy nhiên có những bài toán lớn mà khả năng xử lý của một máy tính thông thường không đáp ứng nổi hoặc cần thời gian xử lý rất lâu. Tại sao không tận dụng khả năng của nhiều máy tính hợp lại để thực hiện tính toán song song? Linux đã trả lời câu hỏi này bằng cách cung cấp một gói phần mềm (package) hỗ trợ lập trình song song.
    Package hỗ trợ lập trình song song không được cài mặc định, vì thế trong quá trình cài đặt Linux bạn phải vào chế độ Custom và đánh dấu chọn Software Development. Chú ý là có thể các phiên bản Linux cũ hơn không có pakage này trong đĩa cài đặt, bạn có thể tải package này từ mạng hoặc liên hệ với tôi theo địa chỉ ở cuối bài viết (Linux 7.3 trở đi chắc chắn có package này).
    Thư viện lập trình song song LAM (Local Area Multicomputer) của Linux là hiện thực của chuẩn lập trình truyền thông điệp (MPI- Message Passing Interface). Để có được kiến thức cơ bản về lập trình song song bạn có thể tham khảo tài liệu [1]. Trong bài viết này tôi chỉ giới thiệu một chương trình song song cơ bản và cách biên dịch chạy trên Linux.

     

    Bài toán xử lý song song đơn giản minh hoạ việc tính tổng một mảng. Cấu trúc chương trình gồm 1 Master và 2 Slave. Master sẽ lưu thông tin về mảng (để đơn giản tôi đã gán giá trị cố định cho mảng, bạn có thể cải tiến chương trình bằng cách nhập giá trị cho mảng từ bàn phím hoặc từ tập tin), chia mảng làm hai phần và giao cho mỗi Slave tính tổng một nửa mảng. Sau đó Master sẽ nhận kết quả trả về từ 2 Slave và thực hiện phép cộng để cho ra kết quả cuối cùng.

    Các bước dịch và chạy chương trình:
    1. Tạo một tập tin schema (ví dụ tập tin lamhosts) chứa tên các máy (hoặc địa chỉ IP) trong mạng mà chương trình song song sẽ chạy trên đó.
    Nếu bạn chỉ có một máy đơn thì tập tin lamhosts sẽ có nội dung như sau:
    127.0.0.1
    2. Khởi động LAM cho các máy. Từ cửa sổ dòng lệnh gõ:

    lamboot  -v  lamhosts
    Lưu ý không nên khởi động LAM từ root.
    3. Giả sử tập tin nguồn có tên là example.c, cách dịch tập tin example.c ra tập tin thực thi example như sau:

    hcc -o example example.c
    4. Để thực thi chương trình này ta cần 3 process, cách thực thi tập tin example như sau:

    mpirun -v -c 3 example

    Muốn chương trình có giao diện đồ hoạ thân thiện hơn, ta có thể dùng công cụ QT Designer có sẵn trong Linux để thiết kế giao diện và cho link tới thư viện LAM. Để có kiến thức về lập trình trên QT Designer, bạn có thể đọc help của chương trình này. Ví dụ trên chạy ở giao diện đồ họa được thể hiện trên hình.

    // Tập tin example.c - ví dụ tính tổng một mảng

    #include 'mpi.h'

    #include

    #define max   5

    double array[2*max]={1,5,4,7,5,8,19,7,6,6};

    void master();

    void slave();

     

    int main( argc, argv )

    int argc;

    char **argv;

    {

       int myrank;

       MPI_Init( &argc, &argv );

              MPI_Comm_rank(MPI_COMM_WORLD,&myrank);

              // Master chạy trên process 0, các Slave chạy trên các process còn lại

       if (myrank==0)  master();

       else  slave();

        MPI_Finalize();

        return 0;

    }

    // Master

    void master(){

              int size,i;

              double newarray[max];

              double firstsum,secondsum,finalsum;

              MPI_Status status;

              MPI_Comm_size(MPI_COMM_WORLD,&size);

              // Gửi nửa mảng đầu cho Slave thứ nhất (process 1)

              for (i=0;i<>< font="">

                       newarray[i]=array[i];}

              MPI_Send(&newarray,max,MPI_DOUBLE,1,0, MPI_COMM_WORLD);

              // Gửi nửa mảng sau cho Slave thứ hai (process 2)

              for (i=max;i<2*max;i++){

                       newarray[i-max]=array[i];}

              MPI_Send(&newarray,max,MPI_DOUBLE,2,0, MPI_COMM_WORLD);

              // Nhận kết quả tính tổng nửa mảng đầu từ Slave thứ nhất (process 1)

              MPI_Recv(&firstsum, 1, MPI_DOUBLE,1, 0,MPI_COMM_WORLD,&status);

              // Nhận kết quả tính tổng nửa mảng sau từ Slave thứ hai (process 2)

              MPI_Recv(&secondsum,1, MPI_DOUBLE,2, 0,MPI_COMM_WORLD,&status);

              // Tính tổng của mảng

      finalsum=firstsum+secondsum;

              // In kết quả

              printf('Tong cua mang la: %.4f\n',finalsum);

    return ;

    }

     

    // Slave

    void slave(){

              int i;

              double newarray[max];

              double result=0;

              MPI_Status status;

              // Nhận mảng từ Master (process 0)

              MPI_Recv(&newarray,max,MPI_DOUBLE,0, 0, MPI_COMM_WORLD,&status);

              // Thực hiện tính tổng

              for (i=0;i<>< font="">

                       result=result+newarray[i];}

              // Gửi kết quả về Master (process 0)

              MPI_Send(&result,1, MPI_DOUBLE,0,0, MPI_COMM_WORLD);

    return ;

    Phạm Đăng Khoa – Ninh Thuận
    dkhoa81@yahoo.com

    ID: A0309_128