【问题标题】:Parallel, Branch & Bound Traveling Salesman via MPI通过 MPI 进行并行、分支和绑定旅行推销员
【发布时间】:2018-08-25 21:05:53
【问题描述】:

我正在努力理解http://wyattgorman.com/?p=25。到目前为止,我所做的不超过clang-format

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

#include <time.h>

#define SIZE 20

int m_row = SIZE, m_column = SIZE, zed = 30, matrix[SIZE][SIZE], visited[SIZE], best_path[SIZE];
int best_cost = 9999999, size = SIZE;

void dfs(int city, int visited_in[], int path_in[], int path_i_in, int cost_in) {

    if (cost_in < best_cost) {

        int* visited = calloc(sizeof(int), size + 1);
        int* path    = calloc(sizeof(int), size + 1);

        int path_i = path_i_in, cost = cost_in, i;

        for (i = 0; i < size; i++) {
            visited[i] = visited_in[i];
            path[i] = path_in[i];
        }

        visited[city] = 1;
        path[path_i] = city;
        path_i++;
        int leaf = 0;

        for (i = 0; i < size; i++) {
            if (visited[i] == 0) {
                leaf++;
                dfs(i, visited.get(), path.get(), path_i, cost + matrix[city][i]);
            }
        }
        if (leaf == 0) {
            cost += matrix[city][0];
            path[path_i] = 0;
            path_i++;

            if (cost < best_cost) {
                // printf("Found new best cost: %i\n", cost);
                best_cost = cost;
                for (i = 0; i < size; i++)
                    best_path[i] = path[i];
            }
        }
        free(visited);
        free(path);
    }
}

int main(int argc, char *argv[]) {
    int rank, p;
// , source, dest;
//     int tag = 0;

    MPI_Status status;
    MPI_Init(0, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &p);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    srand(time(NULL));
    if (rank == 0) {
        int i, j;
        for (i = 0; i < m_row; i++)
            for (j = 0; j < m_column; j++)
                matrix[i][j] = 0;
        for (i = 0; i < m_row; i++) {
            for (j = 0; j < i; j++) {
                if (i != j) {
                    int temp = (rand() % zed) + 1;
                    matrix[i][j] = temp;
                    matrix[j][i] = temp;
                }
            }
        }
        for (i = 1; i < p; i++)
            MPI_Send(&matrix[0][0], size * size, MPI_LONG, i, 0, MPI_COMM_WORLD);

        printf("Matrix, %ix %i, Max Int : %i\n", m_row, m_column, zed);

        for (i = 0; i < m_row; i++) {

            for (j = 0; j < m_column; j++)
                printf("%i\t", matrix[i][j]);
            printf("\n");
            fflush(NULL);
        }
        printf("\n");
        int winner;
        int node_array[p - 1];
        int node_array_i = 0;

        for (i = 0; i < p - 1; i++)
            node_array[i] = i + 1;

        for (i = 1; i < size; i++) {

            int temp_best_cost, node;
            node = node_array[node_array_i];

            if (node_array_i < p - 2)
                node_array_i++;
            else
                node_array_i = 0;

            int* temp_best_path = calloc(sizeof(int), size + 1);

            MPI_Recv(&temp_best_cost, 1, MPI_INT, node, 0, MPI_COMM_WORLD,&status);
            MPI_Recv(&temp_best_path[0], size + 1, MPI_INT, node, 0, MPI_COMM_WORLD, &status);

            if (temp_best_cost < best_cost) {

                winner = node;
                best_cost = temp_best_cost;
                for (j = 0; j < size + 1; j++)
                    best_path[j] = temp_best_path[j];
            }
            MPI_Send(&best_cost, 1, MPI_INT, node, 0, MPI_COMM_WORLD);
        }
        printf("Best Path Found by node % i :\n", winner);
        printf("% i", best_path[0]);

        for (i = 1; i < size + 1; i++)
            printf(" –> % i", best_path[i]);
        printf("\nBest Cost Found : % i\n", best_cost);

    } else {
        MPI_Recv(&(matrix[0][0]), m_row * m_column, MPI_LONG, 0, 0, MPI_COMM_WORLD, &status);

        int i;
        for (i = rank; i < size; i += (p - 1)) {

            int* visited = calloc(sizeof(int), size + 1);
            int* path    = calloc(sizeof(int), size + 1);

            int cost = matrix[0][i], path_i = 1;
            path[0] = 0;
            visited[0] = 1;
            dfs(i, visited.get(), path.get(), path_i, cost);

            MPI_Send(&best_cost, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
            MPI_Send(&best_path[0], size + 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
            MPI_Recv(&best_cost, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);

            free(visited);
            free(path);
        }
    }
    MPI_Finalize();
    return 0;
}

在我看来,它看起来像来自visited[]

int m_row = SIZE, m_column = SIZE, zed = 30, matrix[SIZE][SIZE], visited[SIZE], best_path[SIZE];

被覆盖

int* visited = calloc(sizeof(int), size + 1);

那么,这样可以吗?

此外,在排名中,在

MPI_Recv(&(matrix[0][0]), m_row * m_column, MPI_LONG, 0, 0, MPI_COMM_WORLD, &status);

destination matrix 看起来与 origin matrix 相同(这有意义吗?),排名为 0,位于:

MPI_Send(&matrix[0][0], size * size, MPI_LONG, i, 0, MPI_COMM_WORLD);

既然matrix是所有等级共享的,对吧?

int m_row = SIZE, m_column = SIZE, zed = 30, matrix[SIZE][SIZE], visited[SIZE], best_path[SIZE];

另外,我猜best_path[](在开头)应该是best_path[SIZE+1],而不是best_path[SIZE]。因为循环转到size+1,对吧?

for (j = 0; j < size + 1; j++)
    best_path[j] = temp_best_path[j];

【问题讨论】:

  • 我赞成保留 C++ 标签,如果你允许我,我会说这个问题提到它被移植到 C++。那里已经有 C++ 的东西了。
  • 这个 int node_array[p - 1]; 不是有效的 C++,using std::make_unique; 不是有效的 C - 决定你使用哪种语言
  • 编辑您的问题和代码以反映您所询问的语言。
  • gcc/g++ 实现了一些扩展。这是其中之一。对于visitedvfs 中的声明是全局声明shadowing,直到声明本地版本的范围结束。这被认为是不好的做法(因为它要求读者在使用名称时记住他们得到的是哪一个)但被允许。
  • @NeilButterworth:我希望您已经知道,尽管使用了可变长度自动数组,但 GCC 很乐意将这样的代码编译为 C++。如果这使 GCC 成为“不兼容的 C++ 编译器”,那很好,但事实是它可能是现有最广泛使用的编译器,所以如果 OP 的代码在编写时无法使用,那就有点过分了。

标签: c algorithm mpi graph-algorithm


【解决方案1】:

第一个(全局)visited 变量被用于calloc() 的本地变量“遮蔽”。这不一定是错误的,但它是一种糟糕的编码风格。

是的,矩阵由所有等级共享(对于共享的某些定义)。

至于best_path 结尾之后的写作,您是对的,该代码已损坏(它具有未定义的行为)。

【讨论】:

  • 或者我应该认为每个节点都有自己的`矩阵`?
  • @KcFnMi:​​嗯,每个进程都有自己的matrix,但 0 级进程发送他的版本并覆盖其他进程。顺便说一句,这部分代码看起来也很糟糕——在所有等级的循环中调用MPI_Send() 应该替换为单个广播。总的来说,我对这段代码的质量印象不深——希望你会努力改进它。
猜你喜欢
  • 1970-01-01
  • 2013-09-10
  • 2013-06-09
  • 2015-04-28
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
相关资源
最近更新 更多