Ответ 1
Как и во многих тестах, это действительно зависит от особенностей ситуации. Это правда, что по умолчанию numpy создает массивы в C-смежном (row-major) порядке, поэтому в реферате операции, которые сканируют по столбцам, должны быть быстрее, чем те, которые сканируют по строкам. Однако форма массива, производительность ALU и основной кэш на процессоре оказывают огромное влияние на данные.
Например, на моем MacBook Pro с небольшим целым числом или массивом с плавающей точкой времена аналогичны, но малый целочисленный тип значительно медленнее, чем тип float:
>>> 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