【问题标题】:Fastest Way of Multiplying Arrays in Excel VBA and .NET在 Excel VBA 和 .NET 中乘以数组的最快方法
【发布时间】:2014-05-27 21:50:15
【问题描述】:

我正在尝试尽快将数组相乘。会有非常大的数组,成倍增加很多倍。我有下面使用嵌套循环的代码,有没有更快的方法呢?我有数组 a() 和 b(),我想让 sum(1) = a(1)*b(1) + a(1)*b(2) + a(1)*b(3)等等。

目前我在 Excel VBA 中,但我将很快转换为 VBA.NET。这应该比在 excel vba 中运行它快多少? .Net 中是否有更快的方法可供我使用?

Sub Test()
 ' Just creating the arrays
 Dim a() as Integer, b() as Integer, sum() as Integer, i as Integer, j as Integer
 ReDim a(1 to 3)
 ReDim b(1 to 3)
 ReDim sum(1 to 3)

 For i = 1 to 3 
  a(i) = 2 * i
  b(i) = 3 * i
 Next i

 ' This is my code I am  interested in
 For i = 1 to 3
  For j = 1 to 3
   sum(i) = sum(i) + a(i) * b(j)
  Next j
 Next i

【问题讨论】:

  • “非常大”意味着什么(或至少近似),而“乘以很多倍”意味着什么?如果您担心性能,更准确地说明您将使用的数字规模会有所帮助。
  • sum 似乎将外部产品的行加起来,而不是标准形式的矩阵乘法。标准矩阵乘法需要三个循环,每个元素求和s(i,j) = SUM(a(i,k)*b(k,j),k=1..n)
  • sum(i) 在哪里初始化?您正在使用未初始化的变量。
  • 顺便说一句,根据我的经验,.NETVBA 的 10 倍。

标签: .net vba excel


【解决方案1】:

除非您的示例过于简化,否则您可以通过总结您的 b() 值来移除内部循环,因为

a*p + a*q + a*r + ... + a*z

等价于

a * (p+q+r+...+z)

所以:

Sub Test()

    Dim a(), b(), sum(), i As Long, j As Long, tmp, t, n As Long, tmp2
    ReDim a(1 To 20000)
    ReDim b(1 To 50)
    ReDim sum(1 To 20000)

    For i = 1 To 20000
        a(i) = i / 100
    Next i

    tmp2 = 0
    For i = 1 To 50
        b(i) = i / 100
        tmp2 = tmp2 + b(i)
    Next i

    t = Timer
    For n = 1 To 100
        For i = 1 To 20000
            For j = 1 To 50
             sum(i) = sum(i) + a(i) * b(j)
            Next j
        Next i
    Next n
    Debug.Print Timer - t ' ~5.5sec

    ReDim sum(1 To 20000)

    t = Timer
    For n = 1 To 100
        For i = 1 To 20000
            sum(i) = a(i) * tmp2
        Next i
    Next n
    Debug.Print Timer - t ' ~ 0.1 sec

End Sub

【讨论】:

    【解决方案2】:

    这应该更快:

    ' This is my code I am  interested in
    For i = 1 to 3
      ai = a(i)
      sumi = 0#
      For j = 1 to 3
        sumi = sumi + ai * b(j)
      Next j
      sum(i) = sumi
    Next i
    

    减少查找数组变量的次数应该会有所改善,因为现代处理器需要更长的时间从内存中读取以乘以值。我也会考虑loop unrolling,但您必须使用高性能计时器进行测试,看看是否有帮助。

    【讨论】:

    • 这是一个很好的观点,谢谢。我会阅读循环展开
    猜你喜欢
    • 2016-09-14
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多