如何快速重塑阵列

axs*_*xsk 3 julia

在下面的代码中,我使用Julia Optim包来找到关于目标函数的最优矩阵.遗憾的是,提供的优化函数仅支持向量,因此我必须在将矩阵传递给优化函数之前将其转换为向量,并在将其用于目标函数时将其转换回来.

function opt(A0,X)    
    I1(A) = sum(maximum(X*A,1))

    function transform(A)
      # reshape matrix to vector
      return reshape(A,prod(size(A)))
    end

    function transformback(tA)
      # reshape vector to matrix
      return reshape(tA, size(A0))
    end

    obj(tA) = -I1(transformback(tA))
    result = optimize(obj, transform(A0), method = :nelder_mead)
    return transformback(result.minimum)
end
Run Code Online (Sandbox Code Playgroud)

我认为朱莉娅每次都会为此分配新的空间并且感觉很慢,那么解决这个问题的更有效方法是什么呢?

waT*_*eim 7

只要数组包含被认为是不可变的元素(包括所有基元),那么数组的元素就包含在1个大的连续内存块中.因此,您可以打破维度规则,只需将二维数组视为一维数组,这就是您想要做的.所以你不需要重塑,但我不认为重塑是你的问题

数组是主要的列和连续的

考虑以下功能

function enumerateArray(a)
   for i = 1:*(size(a)...)
      print(a[i])
   end
end
Run Code Online (Sandbox Code Playgroud)

此函数乘以所有的尺寸的一个在一起,然后从1循环到该号码假设一个是一维的.

当您定义如下时

julia> a = [ 1 2; 3 4; 5 6]
3x2 Array{Int64,2}:
 1  2  
 3  4
 5  6
Run Code Online (Sandbox Code Playgroud)

结果是

julia> enumerateArray(a)
135246
Run Code Online (Sandbox Code Playgroud)

这说明了一些事情.

  1. 是的,它确实有效
  2. 矩阵以列主格式存储

重塑

那么,问题是为什么不重塑使用这个事实呢?它确实如此.这是在array.c中重塑的julia源代码

a = (jl_array_t*)allocobj((sizeof(jl_array_t) + sizeof(void*) + ndimwords*sizeof(size_t) + 15)&-16);
Run Code Online (Sandbox Code Playgroud)

所以是的,创建了一个新数组,但只创建了新的维度信息,它指向未复制的原始数据.您可以像这样简单地验证:

 b = reshape(a,6);

julia> size(b)
(6,)

julia> size(a)
(3,2)

julia> b[4]=100
100

julia> a
3x2 Array{Int64,2}:
 1  100
 3    4
 5    6
Run Code Online (Sandbox Code Playgroud)

因此设置的第四元件b组的(1,2)元素一个.

至于整体缓慢

I1(A) = sum(maximum(X*A,1))
Run Code Online (Sandbox Code Playgroud)

将创建一个新的数组.

您可以使用几个宏来跟踪 @profile@time.时间将另外记录分配的内存量,并且可以放在任何表达式的前面.

例如

julia> A = rand(1000,1000);
julia> X = rand(1000,1000);
julia> @time sum(maximum(X*A,1))
elapsed time: 0.484229671 seconds (8008640 bytes allocated)
266274.8435928134
Run Code Online (Sandbox Code Playgroud)

@profile记录的统计信息使用Profile.print()输出