如何在MPI中的进程之间大致均匀地共享工作,尽管数组大小不能被进程数完全整除?
大家好,我有一个长度为N的数组,我想在“大小”处理器之间尽可能最好地划分它。N/size有一个余数,例如1000个数组元素除以7个进程,或14个进程除以3个进程 我知道MPI中至少有几种工作共享方式,例如:如何在MPI中的进程之间大致均匀地共享工作,尽管数组大小不能被进程数完全整除?,mpi,Mpi,大家好,我有一个长度为N的数组,我想在“大小”处理器之间尽可能最好地划分它。N/size有一个余数,例如1000个数组元素除以7个进程,或14个进程除以3个进程 我知道MPI中至少有几种工作共享方式,例如: for(i=rank;i我认为最好的解决方案是为自己编写一个小函数,以便在进程之间足够均匀地分割工作。这里有一些伪代码,我相信你可以比我更好地编写C(你的问题中是C吗?) function split_evenly_enough(num_steps, num_processes) r
for(i=rank;i我认为最好的解决方案是为自己编写一个小函数,以便在进程之间足够均匀地分割工作。这里有一些伪代码,我相信你可以比我更好地编写C(你的问题中是C吗?)
function split_evenly_enough(num_steps, num_processes)
return = repmat(0, num_processes) ! pseudo-Matlab for an array of num_processes 0s
steps_per_process = ceiling(num_steps/num_processes)
return = steps_per_process - 1 ! set all elements of the return vector to this number
return(1:mod(num_steps, num_processes)) = steps_per_process ! some processes have 1 more step
end
以您的“1000个步骤和7个过程”为例
- 简单除法不起作用,因为整数除法(在C中)给了你底数,剩下一些余数:即1000/7是142,将有6个doodas挂在外面
- 天花板分割有一个相反的问题:ceil(1000/7)是143,但最后一个处理器溢出了阵列,或者比其他处理器的任务要少
您要求的是一个在处理器上平均分配剩余部分的方案。一些进程应该有142个,其他的143个。必须有一个更正式的方法,但考虑到这个问题在过去六个月内得到的关注,可能没有
这是我的方法。每个进程都需要做这个算法,只需要为自己挑选出它需要的答案
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char ** argv)
{
#define NR_ITEMS 1000
int i, rank, nprocs;;
int *bins;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
bins = calloc(nprocs, sizeof(int));
int nr_alloced = 0;
for (i=0; i<nprocs; i++) {
remainder = NR_ITEMS - nr_alloced;
buckets = (nprocs - i);
/* if you want the "big" buckets up front, do ceiling division */
bins[i] = remainder / buckets;
nr_alloced += bins[i];
}
if (rank == 0)
for (i=0; i<nprocs; i++) printf("%d ", bins[i]);
MPI_Finalize();
return 0;
}
#包括
#包括
#包括
int main(int argc,字符**argv)
{
#定义NR_项目1000
国际一级,排名,非专利法公约;;
int*垃圾箱;
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI通信大小(MPI通信世界和NPROC);
bins=calloc(nprocs,sizeof(int));
分配的整数=0;
对于(i=0;i如果我有N
任务(例如数组元素)和size
工作者(例如MPI等级),我将如下所示:
int count=N/大小;
整数余数=N%大小;
int启动、停止;
if(秩<余数){
//第一个“剩余”列组每个列组获得“计数+1”个任务
开始=排名*(计数+1);
停止=开始+计数;
}否则{
//剩余的“大小-剩余”列组每个任务获得“计数”
开始=排名*计数+余数;
停止=启动+(计数-1);
}
对于(inti=start;i这个怎么样
int* distribute(int total, int processes) {
int* distribution = new int[processes];
int last = processes - 1;
int remaining = total;
int process = 0;
while (remaining != 0) {
++distribution[process];
--remaining;
if (process != last) {
++process;
}
else {
process = 0;
}
}
return distribution;
}
其思想是将一个元素分配给第一个进程,然后将一个元素分配给第二个进程,然后将一个元素分配给第三个进程,依此类推,只要到达最后一个进程,就跳回第一个进程
即使进程的数量大于元素的数量,这种方法也能工作。它只使用非常简单的操作,因此应该非常快。我也有类似的问题,下面是我使用Python和mpi4py API的非最佳解决方案。最佳解决方案将考虑处理器的布局,这里是额外的工作分配给下级。不均匀的工作量只因一项任务不同而不同,所以一般来说这不是什么大问题
从MPI4p导入MPI
导入系统
def get_start_end(通信,N):
"""
分布N个连续的事物(矩阵的行、1D数组的块)
在给定的通讯器上尽可能均匀。
初始级别上的工作量不均匀(最多相差1)。
参数
----------
通讯器:MPI通讯器
N:int
要分发的内容的总数。
退换商品
----------
rstart:第一个本地行的索引
趋势:1+最后一行的索引
笔记
----------
索引是以零为基础的。
"""
P=通信大小
秩=通信秩
rstart=0
rend=N
如果P>=N:
如果秩=余数:
rstart+=余数
rend+=余数
其他:
rstart+=秩
rend+=排名+1
返回rstart,rend
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
comm=MPI.comm_WORLD
n=int(sys.argv[1])
打印(comm.rank,get\u start\u end(comm,n))
我知道这已经过去很久了,但一个简单的方法是为每个进程指定(项目数)/(进程数)+(如果进程数
# Number of items
NI=128
# Number of processes
NP=20
# Items per process
[NI/NP + (1 if P < NI%NP else 0)for P in range(0,NP)]
#项目数量
NI=128
#进程数
NP=20
#每个流程的项目
[NI/NP+(如果P
这是一个封闭形式的解决方案
设N=数组长度,p=处理器数量
从j=0到p-1
处理器上阵列的起点j=地板(N*j/p)
处理器上阵列的长度j=地板(N*(j+1)/p)–地板(N*j/p)改进@Alexander的答案:利用min
压缩逻辑
int count = N / size;
int remainder = N % size;
int start = rank * count + min(rank, remainder);
int stop = (rank + 1) * count + min(rank + 1, remainder);
for (int i = start; i < stop; ++i) { a[i] = DO_SOME_WORK(); }
int count=N/大小;
整数余数=N%大小;
整数开始=秩*计数+最小值(秩,余数);
整数停止=(秩+1)*计数+min(秩+1,余数);
对于(inti=start;i
内存和时间的复杂性是O(NPROC)。请小心,因为这可能会影响大量进程的内存和性能。