Почему индексирование строк в Python 3.6 в 10 раз медленнее, чем индексирование NumPy? - PullRequest
0 голосов
/ 30 марта 2020

Почему индексирование строк в Python 3 в 10 раз медленнее, чем та же операция с индексированием NumPy?

Код для демонстрации (с использованием I Python magi c для синхронизации):

import numpy as np

vocab = 'abcdefghijklmnopqrstuvwxyz ,-'
vocab_np = np.array(list(vocab))

ind = np.random.randint(0, len(vocab), size=10000)

%timeit s = ''.join(vocab[i] for i in ind)
# 2.86 ms ± 10.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit s = ''.join(vocab_np[ind].tolist())
# 284 µs ± 943 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

(Обратите внимание, что в обоих случаях активно только одно ядро ​​ЦП).

1 Ответ

0 голосов
/ 30 марта 2020

Не go по впечатлениям. Тест!

Фокус на строковой операции:

In [46]: vocab = 'abcdefghijklmnopqrstuvwxyz ,-'                                             
In [47]: ind = np.random.randint(0, len(vocab), size=10000) 
    ...:                                                                                     
In [48]: s = ''.join(vocab[i] for i in ind)                                                  
In [49]: len(s)                                                                              
Out[49]: 10000

Ваш тестовый пример:

In [50]: timeit s = ''.join(vocab[i] for i in ind)                                           
1.9 ms ± 2.14 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

итерация в списке быстрее, чем итерация в массиве:

In [51]: timeit s = ''.join(vocab[i] for i in ind.tolist())                                  
1.06 ms ± 19.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [52]: %%timeit ind1=ind.tolist() 
    ...: s = ''.join(vocab[i] for i in ind1) 
    ...:                                                                      
906 µs ± 511 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

То же самое для l oop немного медленнее:

In [53]: %%timeit ind1=ind.tolist() 
    ...: alist = [] 
    ...: for i in ind1: 
    ...:     alist.append(vocab[i]) 
    ...: ''.join(alist) 
    .                                                                     
1.09 ms ± 372 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Понимание списка может дать более чистый и читаемый код, но это не a основной инструмент скорости. В этом случае vocab[i] все еще выполняется каждый раз. Нет компиляции.

===

Использование понимания списка вместо выражения генератора сокращает время:

In [54]: %%timeit ind1=ind.tolist() 
    ...: s = ''.join([vocab[i] for i in ind1])  
    ...:                                                                                     
641 µs ± 58.7 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

generators хороши, если они кормят больше генераторы в серии, но сами по себе мало что делают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...