2017-01-22 7 views
1

Учитывая сетка 10х10 размера, как это:Разброс сетки в одинаковых по размеру блоков

 0,1,2,3,4,   5,6,7,8,9, 
     10,11,12,13,14,  15,16,17,18,19, 
     20,21,22,23,24,  25,26,27,28,29, 
     30,31,32,33,34,  35,36,37,38,39, 
     40,41,42,43,44,  45,46,47,48,49, 

     50,51,52,53,54,  55,56,57,58,59, 
     60,61,62,63,64,  65,66,67,68,69, 
     70,71,72,73,74,  75,76,77,78,79, 
     80,81,82,83,84,  85,86,87,88,89, 
     90,91,92,93,94,  95,96,97,98,99 

, как рассеивают визуально разделенные блоки до четырех процессов?
Я попытался как описано here (или даже here) с Scatterv, и она работала, но я помню, что проект с точно такой же проблемой и не используя либо изменить размер или Scatterv, чтобы решить эту проблему.

Вот минимальный пример кода с тем, что у меня есть:

#include <stdio.h> 
#include <mpi.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <memory.h> 
#include <unistd.h> 

void print_array(int* arr, int width, int height) 
{ 
    int i; 
    for (i = 0; i< width * height;i++) 
    { 
     if((i != 0) && (i % width == 0)) 
      printf("\n"); 
     printf("%4d ", arr[i]); 
    } 
    putchar('\n'); 
} 

int main() { 
    int board[100] = { 
      0,1,2,3,4,   5,6,7,8,9, 
      10,11,12,13,14,  15,16,17,18,19, 
      20,21,22,23,24,  25,26,27,28,29, 
      30,31,32,33,34,  35,36,37,38,39, 
      40,41,42,43,44,  45,46,47,48,49, 

      50,51,52,53,54,  55,56,57,58,59, 
      60,61,62,63,64,  65,66,67,68,69, 
      70,71,72,73,74,  75,76,77,78,79, 
      80,81,82,83,84,  85,86,87,88,89, 
      90,91,92,93,94,  95,96,97,98,99 
    }; 

    int numprocs, rank; 
    MPI_Init(NULL, NULL); 
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    int* block = calloc(25, sizeof(int)); 
    assert(block != NULL); 


    MPI_Datatype sent_block_t, resized_sent_block_t; 
    MPI_Type_vector(5, 5, 10, MPI_INT, &sent_block_t); 
    MPI_Type_create_resized(sent_block_t, 0, 5*sizeof(int), &resized_sent_block_t); 
    MPI_Type_commit(&sent_block_t); 
    MPI_Type_commit(&resized_sent_block_t); 

    if (rank == 0) { 
     print_array(board, 10, 10); 
     MPI_Scatter(&(board[0]), 1, resized_sent_block_t, 
        &(block[0]), 25, MPI_INT, 
        0, MPI_COMM_WORLD); 
    } 
    else { 
     MPI_Scatter(NULL, 0, resized_sent_block_t, 
        &(block[0]), 25, MPI_INT, 
        0, MPI_COMM_WORLD); 
    } 

    for (int i = 0; i < numprocs; i++) { 
     MPI_Barrier(MPI_COMM_WORLD); 
     sleep(1); 
     if (i == rank) { 
      printf("\nRank: %d\n", rank); 
      print_array(block, 5, 5); 
     } 
    } 

    MPI_Finalize(); 
    free(block); 
} 

Запуск его с 4-мя процессами я получаю это:

0 1 2 3 4 5 6 7 8 9 
    10 11 12 13 14 15 16 17 18 19 
    20 21 22 23 24 25 26 27 28 29 
    30 31 32 33 34 35 36 37 38 39 
    40 41 42 43 44 45 46 47 48 49 
    50 51 52 53 54 55 56 57 58 59 
    60 61 62 63 64 65 66 67 68 69 
    70 71 72 73 74 75 76 77 78 79 
    80 81 82 83 84 85 86 87 88 89 
    90 91 92 93 94 95 96 97 98 99 

Rank: 0 
    0 1 2 3 4 
    10 11 12 13 14 
    20 21 22 23 24 
    30 31 32 33 34 
    40 41 42 43 44 

Rank: 1 
    5 6 7 8 9 
    15 16 17 18 19 
    25 26 27 28 29 
    35 36 37 38 39 
    45 46 47 48 49 

Rank: 2 
    10 11 12 13 14 
    20 21 22 23 24 
    30 31 32 33 34 
    40 41 42 43 44 
    50 51 52 53 54 

Rank: 3 
    15 16 17 18 19 
    25 26 27 28 29 
    35 36 37 38 39 
    45 46 47 48 49 
    55 56 57 58 59 

Это рассеяние не так, обратите внимание на содержание 2-го ранга и 3.
Правильные из них будут:

Rank 0:    Rank 1: 
0,1,2,3,4,   5,6,7,8,9, 
10,11,12,13,14,  15,16,17,18,19, 
20,21,22,23,24,  25,26,27,28,29, 
30,31,32,33,34,  35,36,37,38,39, 
40,41,42,43,44,  45,46,47,48,49, 

Rank 2:    Rank 3: 
50,51,52,53,54,  55,56,57,58,59, 
60,61,62,63,64,  65,66,67,68,69, 
70,71,72,73,74,  75,76,77,78,79, 
80,81,82,83,84,  85,86,87,88,89, 
90,91,92,93,94,  95,96,97,98,99 

Вопрос
Есть ли способ, чтобы рассеять равные по размеру блоков сетки без использования Scatterv?

+0

Итак, вы говорите, что ваш код работает, и вы прекрасно это понимаете. Какая у вас проблема? – Zulan

+0

@ Zulan Нет, результат, который я опубликовал, не является правильным результатом. См. В начале сообщения указанную доску, которая визуально разделяет четыре блока. Я хочу, чтобы левый верхний, чтобы перейти к процессу 0, вверху справа, чтобы обработать 1, в левом нижнем углу для обработки 2 и в левом нижнем углу для обработки 3. (Я добавил ожидаемый результат.) – Chris

+0

Извините, что я только ненадолго снял вывод. Существует [очень хорошее подробное объяснение] (http://stackoverflow.com/a/9271753/620382) о том, как правильно делать то, что вы хотите, используя 'MPI_Scatterv'. Я не могу представить правильную реализацию, используя только «MPI_Scatter», который не бесполезно взломан. – Zulan

ответ

1

Я не думаю, что это возможно сделать с помощью MPI_Scatter, поскольку перемещение типа данных не является постоянным - внутри строки смещение составляет 5 целых чисел (или число 1 с измененным типом), но пропускание до следующая строка представляет собой смещение 50 целых чисел (или count = 10).

4 процессов, с использованием:

int counts[4] = {1, 1, 1, 1}; 
    int disps[4] = {0, 1, 10, 11}; 
    ... 
    if (rank == 0) print_array(board, 10, 10); 

    MPI_Scatterv(&(board[0]), counts, disps, resized_sent_block_t, 
       &(block[0]), 25, MPI_INT, 
       0, MPI_COMM_WORLD); 

, кажется, работает нормально. Обратите внимание, что вам не нужны отдельные вызовы для разбрасывания. MPI гарантирует, что параметры, которые действительны только в корне, всегда упоминаются в корне.