0

我知道这个问题之前已经回答过好几次了,但我检查了所有以前的答案来纠正我的情况,但它没有帮助。

我需要做的是并行化我的循环,以便并行处理每个城市(或内部循环)。但是在使用 parfor 时出现错误“无法对 parfor 中的变量 A 进行分类”。二维矩阵的大小固定为 n X n。我不知道看到问题。请帮帮我...

我提供的 c 实现是使用 mpi.h 完成的。使用 mpicc。我需要实现的是应该有 n 个进程,每个进程负责找到从本地城市到所有其他城市的最短路径。

每个案例都不同。就我而言:

my_first_city=2;
my_last_city=n;
parpool(n-1);

parfor (int_city=2:n,n-1)
% broadcast all --  create threads to handle each city
  for local_city=my_first_city:n
    for city2=2:n
          A(local_city,city2)=min(A(local_city,city2),A(local_city,int_city)+A(int_city,city2));
    end
  end
end

这是我计算最短路径的函数:

function [ A,init ] = floydWarshall(input_matrix, n )
%% Floyd_Warshall algorithm is an analytical algorithm for finding shortest paths in weighted graph ,
%  for example an adjacency matrix or a map graph.
% Floyd_Warshall algorithm compares all possible paths through a graph between each pair of vertices,
% The complexity of this algorithm is O(n^3) where n is the number of vertices, or nodes.
%% Floyd_Warshall
% inputs : 
%       n          = number of vertices to initialize an adjacency matrix.
%    input_matrix  = the input matrix of initial weights or path costs. a nXn matrix
% outputs: 
%       A  = the matrix after floydWarshall algo is applied and the matrix contains the shortest
%            paths from each node to each other node
%     init = The original matrix with all the costs from each node to each other node.
if(nargin<2)
  n=size(input_matrix);
elseif (nargin<1)
   n=size(input_matrix);
   A=magic(n);
end


for i=1:n    % marking the border rows and columns with cities
    A(i,1)=i-1;
    A(1,i)=i-1;
end

for i=1:n    % making sure that the distance from a city i to city i is 0
    A(i,i)=0;
end

for i=2:n   
    for j=2:n
        A(i,j)=input_matrix(i,j);  % input matrix, values 
    end
end


init=A;   % temp variable to store the old matrix
for int_city=2:n
    for city1=2:n
        for city2=2:n
            A(city1,city2)=min(A(city1,city2),A(city1,int_city)+A(int_city,city2));
        end  % floyd-warshall
    end
end
4

2 回答 2

0

这是 MATLAB 中实现 Floyd-Warshall 算法的代码

%%%%% Step 0: Initialization and Parameters %%%%%

N = size(D,1); 
INF =  1000*max(max(D))*N;  %% effectively infinite distance
Y.coords = cell(length(dims),1); 
R = zeros(1,length(dims)); 

%%%%% Step 1: Construct neighborhood graph %%%%%
disp('Constructing neighborhood graph...'); 

K = n_size;
if n_fcn == 'k'
     [~, ind] = sort(D); % For matrices, sort(X) sorts each column of X in ascending order.
     for i=1:N % N is number of points
          D(i,ind((2+K):end,i)) = INF; %setting to infinity distances that more far number of neighborhoods
     end                               %two because we need to have at least one neighbor???
elseif n_fcn == 'epsilon'
     warning off    %% Next line causes an unnecessary warning, so turn it off
     D =  D./(D<=epsilon); 
     D = min(D,INF); 
     warning on
end

D = min(D,D');    %% Make sure distance matrix is symmetric


% Finite entries in D now correspond to distances between neighboring points. 
% Infinite entries (really, equal to INF) in D now correspond to 
%   non-neighoring points. 

%%%%% Step 2: Compute shortest paths %%%%%
disp('Computing shortest paths...'); 

tic; 
for k=1:N
     D = min(D,  repmat(D(:,k),[1 N])  +  repmat(D(k,:),[N 1])  ); % compares each matrix element
     if rem(k,100) == 0 % rem    Remainder after division.
          disp([' Iteration: ', num2str(k), '     Estimated time to completion: ', num2str((N-k)*toc/k/60), ' minutes']); 
     end
end

%%%%% Remove outliers from graph %%%%%
disp('Checking for outliers...'); 
n_connect = sum(~(D==INF));        %% number of points each point connects to 1xN
[~, firsts] = min(D==INF);       %% first point each point connects to
[comps, ~, ~] = unique(firsts);    %% represent each connected component once
size_comps = n_connect(comps);     %% size of each connected component
[~, comp_order] = sort(size_comps);  %% sort connected components by size
comps = comps(comp_order(end:-1:1)); %%move upside down   
size_comps = size_comps(comp_order(end:-1:1)); 
n_comps = length(comps);               %% number of connected components
comp=1;                              %% default: use largest component

disp(['  Number of connected components in graph: ', num2str(n_comps)]); 
disp(['  Embedding component ', num2str(comp), ' with ', num2str(size_comps(comp)), ' points.']); 
Y.index = find(firsts==comps(comp)); 

D = D(Y.index, Y.index); 
N = length(Y.index); 

我知道你可能会得到一些你可以问的问题。顺便说一句,寻找距离的最快算法是 Dijkstra 算法(但你应该在 C 中实现它)。

希望对您有所帮助!我也是新手,但我之前有类似的任务并且代码 100% 正确。

于 2014-10-20T14:56:03.253 回答
0

我相信你的问题是你没有“切片” A matrix

Matlab 中的 parfor 构造创建进程。这意味着所有进程将同时竞争更新变量 A。我不知道 Matlab 是否实现了进程之间的共享内存和正确的同步。好像没有。

如果 Matlab 正在创建线程,那么同步对 A 的访问会更容易,因为所有线程都可以访问它,并且都在一个进程中。流程比较复杂。

所以你的问题是 A 在进程之间共享。为避免此问题,您可以将 A 矩阵拆分为n 个变量(等于进程数),给每个进程一个切片,然后使用 n 个进程给出的输出重构 A。

最好是通过分配 n 个子矩阵(或 n 个子矩阵的数组)手动进行切片。实际上编译器会给你错误,因为它不能自己切片。它需要你去做。

请参阅此处的帖子,描述类似的问题。

祝你好运。

于 2014-10-21T10:50:38.117 回答