3

I did the following matrix multiplication benchmark in IronPython based on code here:

from System import Random
from System.Diagnostics import Stopwatch

def zero(m,n):
    # Create zero matrix
    new_matrix = [[0 for row in range(n)] for col in range(m)]
    return new_matrix

def rand(m,n):
    # Create random matrix
    rnd = Random(1)
    new_matrix = [[rnd.NextDouble() for row in range(n)] for col in range(m)]
    return new_matrix

def show(matrix):
    # Print out matrix
    for col in matrix:
        print col 

def mult(matrix1,matrix2):
    # Matrix multiplication
    if len(matrix1[0]) != len(matrix2):
        # Check matrix dimensions
        print 'Matrices must be m*n and n*p to multiply!'
    else:
        # Multiply if correct dimensions
        watch = Stopwatch()
        print 'mult1 start....'
        watch.Start()
        new_matrix = zero(len(matrix1),len(matrix2[0]))
        for i in range(len(matrix1)):
            for j in range(len(matrix2[0])):
                for k in range(len(matrix2)):
                    new_matrix[i][j] += matrix1[i][k]*matrix2[k][j]
        watch.Stop()
        print 'mult1 end.'
        print watch.ElapsedMilliseconds
        return new_matrix

from System import Array

def ListToArray(matrix):
    n = len(matrix)
    m = len(matrix[0])
    a = Array.CreateInstance(float, n, m)
    for i in range(n):
        for j in range(m):
            a[i,j] = matrix[i][j]
    return a


def mult2(matrix1, matrix2):

    N = len(matrix1)
    K = len(matrix2)
    M = len(matrix2[0])

    m1 = ListToArray(matrix1)
    m2 = ListToArray(matrix2)
    res = ListToArray(rand(len(matrix1), len(matrix2[0])))

    watch = Stopwatch()
    print 'mult2 start...'
    watch.Start()
    for i in range(N):
        for j in range(M):
            for k in range(K):
                res[i,j] += m1[i,k]*m2[k,j]
    watch.Stop()
    print 'mult2 ends.'
    print watch.ElapsedMilliseconds
    return res


if __name__ == '__main__':
    #a = rand(280,10304)
    #b = rand(10304,280)

    a = rand(280,10)
    b = rand(10,280)

    c = mult2(a, b)
    d = mult(a, b)

I want to try two big matrices (280 by 10304 and 10304 by 208), but both versions cannot produce a result within a short time.

Then I tried a much smaller one (as show in the code), I the result is following:

mult2 : 7902 ms
mult1 : 420 ms

indicating that using .NET array in IronPython is much slower than the python List.

Also notice that C# uses about ~12 seconds for the two big matrices. IronPython already spends a lot of them on the 10K times smaller case. I am not sure whether the IronPython setting in my computer is wrong or not, if not, IronPython is really slow for numerical code.

5
  • It would be great, if you'd use a C# (or any other 'pure' CLR language) benchmark to test the same code. Then you can definitely find out, is the .NET or IronPython is the reason. Commented Jun 1, 2011 at 10:37
  • @Zaur, see my post, I've already used C# and got the timing. Commented Jun 1, 2011 at 10:51
  • Oh, sorry. Well, I just can say that any kind of Python should not used for numerical methods, there is NumPy if you need that kind of performance. Yet, you can compile a DLL in C# and use it in your IronPython code. Commented Jun 1, 2011 at 10:57
  • You could also look into Cobra and Boo. Both are .net languages with python like syntax, but they offer a mix of static and dynamic typing. So you can use static typing in your performance critical code parts to get the same performance as C#. IMO Cobra has the better language design of the two, but the IDE support for Boo is better. Commented Jun 1, 2011 at 11:17
  • You need to look SciPy for Ironpython - See pytools.codeplex.com for more information. And why is res not a Zero matrix to begin like new_matrix is in mult? Commented Jun 1, 2011 at 17:40

4 Answers 4

2

For your particular question, I think the problem is boxing - in IronPython, list items (and all other variables) are stored boxed, so only boxed values are operated on. CLR Array elements are not boxed, however, and thus IronPython will have to box them when they are extracted from the array, and then unbox them on the way back in. C# can operate on the unboxed values, and has a bunch of other optimizations to make arrays fast that IronPython doesn't have.

If you want fast numerical math, NumPy for IronPython might be a better bet.

Sign up to request clarification or add additional context in comments.

Comments

1

In our projects we are trying to avoid .Net classes usage until this become really necessary. I guess that there is no any particular need to use Array for matrix multiplication since python gives you several ways to handle matrices like list, collections or numpy.

Comments

0

You're likely to get slow speeds one way or another when using a high level language to process matrices. If you want to do it in .net, try http://numerics.mathdotnet.com/ - they've done what's possible to improve matrix operations already.

It's not really an answer to why you see the difference, but might help if you're looking for some fast solution.

Comments

0

My guess is what's killing the performance vs. normal Python lists is the use of a multi-dimensional array. I could easily see this being a slow path and that if you switched to arrays of arrays or calculating the index yourself you could see a big speed up.

Others have pointed out that this isn't the best code for a dynamic language like Python. But one of the great benefits of IronPython is how easy and seamless it is to pull in C# snippets to speed up cases like this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.