.NET массив медленнее, чем список в IronPython? - PullRequest
3 голосов
/ 01 июня 2011

Я провел следующий тест умножения матриц в IronPython на основе кода здесь :

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)

Я хочу попробовать две большие матрицы (280 на 10304 и 10304 на 208), нообе версии не могут дать результат в течение короткого времени.

Затем я попробовал гораздо меньший (как показано в коде) результат: 1008 *

mult2 : 7902 ms
mult1 : 420 ms

, указывающий, что использование массива .NET в IronPython намного медленнее, чем в PythonСписок.

Также обратите внимание, что C # использует около 12 секунд для двух больших матриц.IronPython уже тратит много из них на 10K раз меньше.Я не уверен, что настройка IronPython на моем компьютере неправильная или нет, если нет, IronPython действительно медленно обрабатывает числовой код.

Ответы [ 4 ]

2 голосов
/ 02 июня 2011

По вашему конкретному вопросу, я думаю, проблема в боксе - в IronPython элементы списка (и все другие переменные) хранятся в штучной упаковке, поэтому работают только с коробочными значениями.Однако элементы массива CLR не упакованы, и поэтому IronPython должен будет блокировать их при извлечении из массива, а затем распаковывать их по пути назад. C # может работать с распакованными значениями и имеет множество других оптимизацийчтобы быстро создавать массивы, которых нет у IronPython.

Если вы хотите быструю числовую математику, лучше подойдет NumPy для IronPython .

1 голос
/ 03 июня 2011

В наших проектах мы стараемся избегать использования классов .Net, пока это не станет действительно необходимым. Я предполагаю, что нет особой необходимости использовать Array для умножения матриц, так как python дает вам несколько способов обработки матриц, таких как list, collection или numpy.

0 голосов
/ 04 июня 2011

Мне кажется, что убивание производительности по сравнению с обычными списками Python - это использование многомерного массива.Я мог бы легко увидеть, что это медленный путь, и что если вы переключитесь на массивы массивов или рассчитаете индекс самостоятельно, вы увидите большую скорость.

Другие отметили, что это не лучший код длядинамический язык, такой как Python.Но одно из больших преимуществ IronPython заключается в том, насколько легко и плавно использовать фрагменты C # для ускорения подобных случаев.

0 голосов
/ 01 июня 2011

При использовании языка высокого уровня для обработки матриц вы, вероятно, получите медленные скорости. Если вы хотите сделать это в .net, попробуйте http://numerics.mathdotnet.com/ - они уже сделали все возможное, чтобы улучшить матричные операции.

Это не совсем ответ на вопрос, почему вы видите разницу, но может помочь, если вы ищете какое-то быстрое решение.

...