Резоны для потенциально плохой работы numpy?

#python #arrays #performance #numpy #tensorflow

Вопрос:

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

 import timeit
import numpy as np
import tensorflow as tf

def np_dot(U, X):
    tic = timeit.default_timer()
    X_bar = np.dot(U.T, X)
    toc = timeit.default_timer()
    print("np.dot took {:.4f} s".format(toc-tic))
    return X_bar

def np_at(U, X):
    tic = timeit.default_timer()
    X_bar = U.T @ X
    toc = timeit.default_timer()
    print("np @ took {:.4f} s".format(toc-tic))
    return X_bar

def np_matmul(U, X):
    tic = timeit.default_timer()
    X_bar = np.matmul(U.T, X)
    toc = timeit.default_timer()
    print("np.matmul took {:.4f} s".format(toc-tic))
    return X_bar

def np_einsum(U, X):
    tic = timeit.default_timer()
    X_bar = np.einsum('ij,jk', U.T, X)
    toc = timeit.default_timer()
    print("np.einsum took {:.4f} s".format(toc-tic))
    return X_bar

def tf_matmul(U, X):
    tic = timeit.default_timer()
    X_bar = tf.matmul(U.T, X)
    toc = timeit.default_timer()
    print("tf.matmul took {:.4f} s".format(toc-tic))
    return X_bar


if __name__ == "__main__":
    print("is_gpu_available?", tf.test.is_gpu_available(), tf.test.is_built_with_cuda())
    print("numpy version:", np.__version__)
    print("tensorflow version:", tf.__version__)
    
    M = N = 1000
    X = np.random.rand(M, N)
    U = np.random.rand(M, N)
    X_bar = np_dot(U, X)
    X_bar0 = np_at(U, X)
    X_bar1 = np_matmul(U, X)
    X_bar2 = np_einsum(U, X)
    X_bar3 = tf_matmul(U, X)
    print(np.allclose(X_bar, X_bar0))
    print(np.allclose(X_bar, X_bar1))
    print(np.allclose(X_bar, X_bar2))
    print(np.allclose(X_bar, X_bar3))
 

Вывод на моем ноутбуке (с Windows 10 и python 3.8) :

 is_gpu_available? False False
numpy version: 1.19.2
tensorflow version: 2.2.0
np.dot took 12.5368 s
np @ took 14.3303 s
np.matmul took 14.0634 s
np.einsum took 0.5937 s
tf.matmul took 0.0263 s
True
True
True
True
 

это означает, что стандарт @ работает в 545 раз медленнее, чем мог бы быть! На ноутбуке друзей результат выглядит больше, чем ожидалось (с Ubuntu и python 3.6.9).:

 is_gpu_available? False False
numpy version: 1.19.5
tensorflow version: 1.14.0
np.dot took 0.0192 s
np @ took 0.0196 s
np.matmul took 0.0208 s
np.einsum took 0.3893 s
tf.matmul took 0.0280 s
True
True
True
True
 

Interestingly, numpys einsum does not seem to be affected by whatever is going wrong on my laptop and neither is tensorflow.

Что здесь происходит? Каковы потенциальные причины такой огромной разницы в производительности?

Редактировать:

Всегда убедитесь, что numpy использует какую-нибудь библиотеку BLAS. Подробнее об этом читайте здесь: Повышение numpy: Почему BLAS имеет значение.

В моем случае numpy.show_config() возвращает следующее:

 blas_mkl_info:
  NOT AVAILABLE
blis_info:
  NOT AVAILABLE
openblas_info:
  NOT AVAILABLE
atlas_3_10_blas_threads_info:
  NOT AVAILABLE
atlas_3_10_blas_info:
  NOT AVAILABLE
atlas_blas_threads_info:
  NOT AVAILABLE
atlas_blas_info:
  NOT AVAILABLE
accelerate_info:
  NOT AVAILABLE
blas_info:
  NOT AVAILABLE
blas_src_info:
  NOT AVAILABLE
blas_opt_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
openblas_lapack_info:
  NOT AVAILABLE
openblas_clapack_info:
  NOT AVAILABLE
flame_info:
  NOT AVAILABLE
atlas_3_10_threads_info:
  NOT AVAILABLE
atlas_3_10_info:
  NOT AVAILABLE
atlas_threads_info:
  NOT AVAILABLE
atlas_info:
  NOT AVAILABLE
lapack_info:
  NOT AVAILABLE
lapack_src_info:
  NOT AVAILABLE
lapack_opt_info:
  NOT AVAILABLE
numpy_linalg_lapack_lite:
    language = c
    define_macros = [('HAVE_BLAS_ILP64', None), ('BLAS_SYMBOL_SUFFIX', '64_')]
 

Комментарии:

1. что такое BAS/LAPACK, с помощью которого был построен ваш numpy? что вам numpy.show_config() это дает?

2. короче говоря: blas_mkl_info, blis_info, openblas_info, atlas_3_10_blas_threads_info, atlas_3_10_blas_info, atlas_blas_threads_info, atlas_blas_info, accelerate_info, blas_info, blas_src_info, blas_opt_info, lapack_mkl_info, openblas_lapack_info, openblas_clapack_info, flame_info, atlas_3_10_threads_info, atlas_3_10_info, atlas_threads_info, atlas_info, lapack_info, lapack_src_info, lapack_opt_info: НЕДОСТУПНО numpy_linalg_lapack_lite: язык = c define_macros = [(‘HAVE_BLAS_ILP64’, Нет), (‘BLAS_SYMBOL_SUFFIX’, ’64_’)]

3. Вам действительно следует отредактировать свой вопрос и добавить его туда…

4. Похоже, что ваша установка numpy не использует библиотеку BLAS или LAPACK . Что определенно объяснило бы эту проблему с производительностью

5. Спасибо! Я использовал ParaView Python, который почему-то не использовал BLAS. Другой интерпретатор Python на моей машине работает просто отлично.