Vector 并行重新排列矢量以实现快速性能

Vector 并行重新排列矢量以实现快速性能,vector,parallel-processing,fortran,fortran90,Vector,Parallel Processing,Fortran,Fortran90,我有一个向量,它的长度可以达到几百万或者更多 如果我说向量是vec=[a1 a2…b1 b2…c1 c2…d1 d2…] 我需要将vec重新排列为new_-vec=[a1 b1 c1 d1 a2 b2 c2 d2…] 如果将其视为列向量的矩阵,则可以将其视为转置,但我没有二维向量。我知道如何在顺序计算机上做这件事。这很简单 但我不知道如何在多处理器集群或GPU上做到这一点,甚至不知道这在并行机上是否可行。内存似乎是明显的瓶颈。如果我可以使用任何算法或任何特定于体系结构的优化,请告诉我 编辑:更多

我有一个向量,它的长度可以达到几百万或者更多

如果我说向量是
vec=[a1 a2…b1 b2…c1 c2…d1 d2…]

我需要将
vec
重新排列为
new_-vec=[a1 b1 c1 d1 a2 b2 c2 d2…]

如果将其视为列向量的矩阵,则可以将其视为转置,但我没有二维向量。我知道如何在顺序计算机上做这件事。这很简单

但我不知道如何在多处理器集群或GPU上做到这一点,甚至不知道这在并行机上是否可行。内存似乎是明显的瓶颈。如果我可以使用任何算法或任何特定于体系结构的优化,请告诉我

编辑:更多信息如下

代码结构为:

subroutine reorder(vec,parameter)

real(kind = 8),dimension(parameter%length), intent(inout) :: vec
real(kind = 8),dimension(parameter%length) :: temp
type(param)                                :: parameter !just a struct holding certain constant parameters
integer                                    :: i,j,k,q1,q2,q3,nn1,n1,n2,nn2

i1 = parameter%len1    !lengths of sub-vectors in each direction 
i2 = parameter%len2    !the multiplication of the 3 gives the 
                       !overall length of vec
i3 = parameter%len3

temp = vec

n1 = i2*i1
n2 = i2*i3
   do k = 1, i3
      q1 = n1*(k-1)
      q2 = i2*(k-1)
      do j = 1, i2
         q3 = i1*(j-1)
         do i = 1, i1
            nn1 = q1+q3+i
            nn2 = q2+j+n2*(i-1)
            vec(nn2) = temp(nn1)
         end do
      end do
   end do

end subroutine reorder
因此,代码旨在根据规则对向量的元素进行重新排序。正如您可以看到的,随着向量的长度变得非常大,在这个例程中花费了大量的时间

在主例程中多次调用此例程。笛卡尔分解在开始时生成列组的笛卡尔3D排列,当需要对元素进行重新排序以进行其自己的下一个子例程调用时,每个列组调用此子例程。笛卡尔通讯器子例程如下图所示:

subroutine cartesian_comm(ndim,comm_cart,comm_one_d,coord_cart)
use mpi
implicit none
integer, dimension(:), intent(in)  :: ndim
integer,               intent(out) :: comm_cart
integer, dimension(:), pointer     :: comm_one_d, coord_cart
logical, dimension(size(ndim))     :: period, remain
integer :: dim,code, i, rank

!creating the cartesian communicator
dim = 3
allocate(comm_one_d(dim),coord_cart(dim))
period   = .FALSE.
call MPI_CART_CREATE(MPI_COMM_WORLD, dim, ndim, period, .FALSE., comm_cart, code)
call MPI_COMM_RANK(comm_cart, rank, code)
call MPI_CART_COORDS(comm_cart, rank, dim, coord_cart, code)

!Creating sub-communicator for each direction
do i = 1, dim
   remain = .FALSE.
   remain(i) = .TRUE.
   call MPI_CART_SUB(comm_cart, remain, comm_one_d(i), code)
end do
end subroutine cartesian_comm
在main函数中调用它,如下所示:

Program main
!initialize some stuff and intialize all the required variables

! ndim is the number of processes the program is called 
! with "mpirun -np 8 ./exec" would mean ndim is cuberoot of 8,
! and therefore 2 for the 3D case. It is always made sure that
! np is a cube(or square for 2D) while calling the program

call cartesian_comm(ndim,comm_cart,comm_one_d,coord_cart)

  do while (t<tend-1D-8)  !start time loop
    t = t + dt
    !do some computations get the vector "vec" for 
    !each rank separately (different and independent in each rank)

    call reorder(vec,parameter) ! all ranks call this subroutine

    !do some computations here with the new reordered vec

  end do !end time loop

!do other stuff (unrelated to reorder but use the "vec" vector) here

end Program main
主程序
!初始化一些内容并初始化所有必需的变量
! ndim是程序调用的进程数
! 使用“mpirun-np 8./exec”意味着ndim是8的cuberoot,
! 因此,3维情况下为2。我们总是确保
! np是调用程序时的立方体(或二维正方形)
调用笛卡尔通信(ndim、通信车、通信一车、协调车)

这在我看来很广泛。使用集群和加速器(GPU)是完全独立的。你可以同时做这两件事,也可以只做一件事。如果你的向量分布在集群的几个节点上,一切都会改变。你真的需要至少知道它是否分布,如果是,具体如何。它会改变一切。我需要重新排列…真的吗?你需要吗?有时这样的needs再进一步考虑一下。也许你需要以非单位步长跨过它?如果你解释你为什么问这个问题,你可能会得到你应该问的问题的答案。或者没有。我在多个处理器上计算向量的元素,然后在主处理器上收集它们。因此向量是not分布在处理器之间,但仅出现在主处理器上。在我重新排列之后,我再次将它们发送给所有处理器。在一些计算之后,这个过程迭代重复。由于向量很大,这种恒定的交换被证明是非常低效的。非单位步幅不是一个选项,因为这样我就没有连续的memory访问,而且效率也会很低。我认为你必须准确地描述你在问题中所做的事情。编辑它!展示一些代码!你应该思考如何避免在一个处理器上进行所有收集。想想像MPI_AllToAll()这样的事情.您是在使用MPI还是实际使用的?请具体说明!F90中有重塑功能…您考虑过吗?这在我看来非常广泛。使用群集和加速器(GPU)是完全独立的。你可以同时做这两件事,也可以只做一件事。如果你的向量分布在集群的几个节点上,一切都会改变。你真的需要至少知道它是否分布,如果是,具体如何。它会改变一切。我需要重新排列…真的吗?你需要吗?有时这样的needs再进一步考虑一下。也许你需要以非单位步长跨过它?如果你解释你为什么问这个问题,你可能会得到你应该问的问题的答案。或者没有。我在多个处理器上计算向量的元素,然后在主处理器上收集它们。因此向量是not分布在处理器之间,但仅出现在主处理器上。在我重新排列之后,我再次将它们发送给所有处理器。在一些计算之后,这个过程迭代重复。由于向量很大,这种恒定的交换被证明是非常低效的。非单位步幅不是一个选项,因为这样我就没有连续的memory访问,而且效率也会很低。我认为你必须准确地描述你在问题中所做的事情。编辑它!展示一些代码!你应该思考如何避免在一个处理器上进行所有收集。想想像MPI_AllToAll()这样的事情.您使用的是MPI还是实际使用的?请具体说明!F90中有重塑功能…您考虑过吗?