当前位置 : 主页 > 网络安全 > 测试自动化 >

性能 – 为了使用列式操作,转置数组是否有益?

来源:互联网 收集:自由互联 发布时间:2021-06-22
假设我们正在使用以列为主的顺序存储数组的语言.还假设我们有一个使用二维数组作为参数的函数,并返回它. 我想知道你是否可以声称,在调用函数时,为了使用逐列操作而不是逐行操作
假设我们正在使用以列为主的顺序存储数组的语言.还假设我们有一个使用二维数组作为参数的函数,并返回它.
我想知道你是否可以声称,在调用函数时,为了使用逐列操作而不是逐行操作,转换此数组通常是有利的(或者不是),或者转置否定了逐列操作的好处?

例如,在R中,我有一个名为y的类ts的对象,它具有维数n x p,即我有p次系列的长度为n.

我需要在Fortran中使用y进行一些计算,其中我有两个循环,具有以下类型的结构:

do i = 1, n
  do j= 1, p
   !just an example, some row-wise operations  on `y`
   x(i,j) = a*y(i,j) 
   D = ddot(m,y(i,1:p),1,b,1) 
   ! ...
  end do
end do

由于Fortran(与R一样)使用列式存储,因此最好使用p x n数组进行计算.而不是

out<-.Fortran("something",y=array(y,dim(y)),x=array(0,dim(y)))
ynew<-out$out$y
x<-out$out$x

我可以用

out<-.Fortran("something2",y=t(array(y,dim(y))),x=array(0,dim(y)[2:1]))
ynew<-t(out$out$y)
x<-t(out$out$x)

Fortran子例程中的东西2会是这样的

do i = 1, n
  do j= 1, p
   !just an example, some column-wise operations  on `y`
   x(j,i) = a*y(j,i) 
   D = ddot(m,y(1:p,i),1,b,1) 
   ! ...
  end do
end do

方法的选择是否总是取决于维度n和p,或者可以说一种方法在计算速度和/或内存要求方面更好?在我的应用中,n通常远大于p,在大多数情况下为1到10.

更多的评论,买我想要一些代码:在旧学校f77下你基本上会被迫使用第二种方法作为

y(1:p,i)

只是指向y(1,i)的指针,其中p值在内存中是连续的.

第一个结构

y(i,1:p)

是一个间隔在内存中的值列表,因此似乎需要将数据的副本传递给子例程.我说这似乎是因为我不知道现代优化编译器如何处理这些事情.在最坏的情况下,我倾向于认为它最好是冲洗,这可能真的很痛.想象一个如此大的数组,你需要页面交换来访问整个向量.

最后,解决这个问题的唯一方法就是自己测试一下

– – – – – 编辑
做了一点测试并确认了我的预感:传递行y(i,1:p)确实花费你和传递列y(1:p,i).我使用的子程序几乎没有什么可以看出差异.我对任何真正的子程序的猜测都是可以忽略不计的.

顺便说一句(也许这有助于理解发生了什么)在列中传递其他所有值

y(1:p:2,i)比通过整列需要更长(数量级),而连续传递每隔一个值会将时间减少一半而不是通过整行.

(使用gfortran 12 ..)

网友评论