2013-07-30 6 views
11

Есть a few articles, которые показывают, что MATLAB предпочитает операции столбцов, чем операции с строками, и что в зависимости от вас выкладывают ваши данные с производительностью can vary significantly. По-видимому, это связано с тем, что MATLAB использует порядок column-major для представления массивов.Выполнение операций строк и столбцов в NumPy

Помню, что Python (NumPy) использует заказ row-major. С этим моими вопросами являются:

  1. Можно ли ожидать аналогичной разницы в производительности при работе с NumPy?
  2. Если ответ на все вышеизложенное да, то какие были бы примеры, которые подчеркивают эту разницу?
+0

Вы могли бы хотеть, чтобы проверить [это] (http://stackoverflow.com/questions/17840661). Это недавний пример, где большая разница в операциях над разными осями. Хотя это, скорее всего, будет ошибкой. – Daniel

ответ

11

Как и многие контрольные показатели, это действительно зависит от особенностей ситуации. Это правда, что по умолчанию numpy создает массивы в C-смежном (row-major) порядке, поэтому в реферате операции, которые сканируют по столбцам, должны быть быстрее, чем те, которые сканируют по строкам. Однако форма массива, производительность ALU и основной кэш на процессоре оказывают огромное влияние на данные.

Например, на моем MacBook Pro с небольшим целым числом или поплавок массив, времена похожи, но небольшое число типа значительно медленнее, чем тип поплавка:

>>> x = numpy.ones((100, 100), dtype=numpy.uint8) 
>>> %timeit x.sum(axis=0) 
10000 loops, best of 3: 40.6 us per loop 
>>> %timeit x.sum(axis=1) 
10000 loops, best of 3: 36.1 us per loop 

>>> x = numpy.ones((100, 100), dtype=numpy.float64) 
>>> %timeit x.sum(axis=0) 
10000 loops, best of 3: 28.8 us per loop 
>>> %timeit x.sum(axis=1) 
10000 loops, best of 3: 28.8 us per loop 

с большими массивами Абсолютной различия становятся больше, но, по крайней мере, на моей машине еще меньше для большего типа данных:

>>> x = numpy.ones((1000, 1000), dtype=numpy.uint8) 
>>> %timeit x.sum(axis=0) 
100 loops, best of 3: 2.36 ms per loop 
>>> %timeit x.sum(axis=1) 
1000 loops, best of 3: 1.9 ms per loop 

>>> x = numpy.ones((1000, 1000), dtype=numpy.float64) 
>>> %timeit x.sum(axis=0) 
100 loops, best of 3: 2.04 ms per loop 
>>> %timeit x.sum(axis=1) 
1000 loops, best of 3: 1.89 ms per loop 

Вы можете сказать, NumPy создать Fortran-смежный (столбцы) массив, используя аргумент order='F' ключевого слова, чтобы numpy.asarray, numpy.ones, numpy.zeros и т.п., или путем преобразования существующего массива с использованием numpy.asfortranarray. Как и следовало ожидать, эта упорядоченность свопы эффективность строк или столбцов операций:

in [10]: y = numpy.asfortranarray(x) 
in [11]: %timeit y.sum(axis=0) 
1000 loops, best of 3: 1.89 ms per loop 
in [12]: %timeit y.sum(axis=1) 
100 loops, best of 3: 2.01 ms per loop 
0

Я подозреваю, что он будет отличаться в зависимости от данных и операций.

Простой ответ заключается в том, чтобы написать некоторые тесты, используя тот же самый реальный мир, данные того типа, который вы планируете использовать, и функции, которые вы планируете использовать, а затем используйте cprofile или timeit для сравнения скоростей, для ваших в зависимости от того, как вы структурируете свои данные.

2
In [38]: data = numpy.random.rand(10000,10000) 

In [39]: %timeit data.sum(axis=0) 
10 loops, best of 3: 86.1 ms per loop 

In [40]: %timeit data.sum(axis=1) 
10 loops, best of 3: 101 ms per loop 
Смежные вопросы