visualizar varianza normalizar libreria estandar estadistica desviacion datos con analisis python performance types numpy benchmarking

varianza - Tipos de datos de Python Numpy Rendimiento



python visualizar datos (2)

La aritmética de media precisión (float16) es algo que debe ser "emulado" por el número, supongo, ya que no hay tipos correspondientes en el lenguaje C subyacente (y en las instrucciones apropiadas del procesador) para ello. Por otro lado, las operaciones de precisión simple (float32) y de precisión doble (float64) pueden realizarse de manera muy eficiente utilizando tipos de datos nativos.

A partir del buen rendimiento para operaciones de precisión simple: los procesadores modernos tienen unidades eficientes para la aritmética de punto flotante vectorizada (por ejemplo, AVX), ya que también se necesita para un buen rendimiento multimedia.

Así que hice algunas pruebas y obtuve resultados extraños.

Código:

import numpy as np import timeit setup = """ import numpy as np A = np.ones((1000,1000,3), dtype=datatype) """ datatypes = "np.uint8", "np.uint16", "np.uint32", "np.uint64", "np.float16", "np.float32", "np.float64" stmt1 = """ A = A * 255 A = A / 255 A = A - 1 A = A + 1 """ #~ np.uint8 : 1.04969205993 #~ np.uint16 : 1.19391073202 #~ np.uint32 : 1.37279821351 #~ np.uint64 : 2.99286961148 #~ np.float16 : 9.62375889588 #~ np.float32 : 0.884994368045 #~ np.float64 : 0.920502625252 stmt2 = """ A *= 255 A /= 255 A -= 1 A += 1 """ #~ np.uint8 : 0.959514497259 #~ np.uint16 : 0.988570167659 #~ np.uint32 : 0.963571471946 #~ np.uint64 : 2.07768933333 #~ np.float16 : 9.40085450056 #~ np.float32 : 0.882363984225 #~ np.float64 : 0.910147440048 stmt3 = """ A = A * 255 / 255 - 1 + 1 """ #~ np.uint8 : 1.05919667881 #~ np.uint16 : 1.20249978404 #~ np.uint32 : 1.58037744789 #~ np.uint64 : 3.47520357571 #~ np.float16 : 10.4792515701 #~ np.float32 : 1.29654744484 #~ np.float64 : 1.80735079168 stmt4 = """ A[:,:,:2] *= A[:,:,:2] """ #~ np.uint8 : 1.23270964172 #~ np.uint16 : 1.3260807837 #~ np.uint32 : 1.32571002402 #~ np.uint64 : 1.76836543305 #~ np.float16 : 2.83364821535 #~ np.float32 : 1.31282323872 #~ np.float64 : 1.44151875479 stmt5 = """ A[:,:,:2] = A[:,:,:2] * A[:,:,:2] """ #~ np.uint8 : 1.38166223494 #~ np.uint16 : 1.49569114821 #~ np.uint32 : 1.53105315419 #~ np.uint64 : 2.03457943366 #~ np.float16 : 3.01117795524 #~ np.float32 : 1.51807271679 #~ np.float64 : 1.7164808877 stmt6 = """ A *= 4 A /= 4 """ #~ np.uint8 : 0.698176392658 #~ np.uint16 : 0.709560468038 #~ np.uint32 : 0.701653066443 #~ np.uint64 : 1.64199069295 #~ np.float16 : 4.86752675499 #~ np.float32 : 0.421001675475 #~ np.float64 : 0.433056710408 stmt7 = """ np.left_shift(A, 2, A) np.right_shift(A, 2, A) """ #~ np.uint8 : 0.381521115341 #~ np.uint16 : 0.383545967785 #~ np.uint32 : 0.386147272415 #~ np.uint64 : 0.665969478824 for stmt in [stmt1, stmt2, stmt3, stmt4, stmt5, stmt6, stmt7]: print stmt for d in datatypes: s = setup.replace("datatype", d) T = timeit.Timer(stmt=stmt, setup=s) print d,":", min(T.repeat(number=30)) print print

¿Por qué es tan lento el float16? ¿Por qué es tan rápido float32? A menudo es más rápido que las operaciones enteras.

Si tiene algún consejo relacionado con el rendimiento, me encantaría escucharlos.

Esto es Python 2.6.6 32 bits en Windows 8 64 bits. Números para Numpy 1.6, Numpy 1.7 similares. Probaré la versión optimizada de MKL ahora: http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy

edit: resulta que la versión MKL es ligeramente más rápida en algunos casos de punto flotante pero a veces mucho más lenta para operaciones con enteros:

stmt2 = """ A *= 255 A /= 255 A -= 1 A += 1 """ #np1.6 #~ np.uint8 : 0.959514497259 #~ np.uint16 : 0.988570167659 #~ np.uint32 : 0.963571471946 #~ np.uint64 : 2.07768933333 #~ np.float16 : 9.40085450056 #~ np.float32 : 0.882363984225 #~ np.float64 : 0.910147440048 # np1.7 #~ np.uint8 : 0.979 #~ np.uint16 : 1.010 #~ np.uint32 : 0.972 #~ np.uint64 : 2.081 #~ np.float16 : 9.362 #~ np.float32 : 0.882 #~ np.float64 : 0.918 # np1.7 mkl #~ np.uint8 : 1.782 #~ np.uint16 : 1.145 #~ np.uint32 : 1.265 #~ np.uint64 : 2.088 #~ np.float16 : 9.029 #~ np.float32 : 0.800 #~ np.float64 : 0.866


Los números de punto flotante de 16 bits no son compatibles directamente con la mayoría de las CPU comunes (aunque los proveedores de tarjetas gráficas parecen estar involucrados en este tipo de datos, por lo que espero que las GPU lo admitan eventualmente). Espero que sean emulados, de una manera relativamente lenta. Google me dice que float16 dependía del hardware y algunas personas querían emularlo para hardware que no lo admite, aunque no encontré nada sobre si eso sucedió realmente.

Por otra parte, los flotadores de 32 bits no solo son compatibles de forma nativa, también puede vectorizar muchas operaciones con las extensiones de conjuntos de instrucciones SIMD, lo que reduce drásticamente la sobrecarga para el tipo de operación que evalúa. La excepción es la mezcla de datos, pero en ese caso, float32 está a la par con int32 y ambos pueden usar las mismas instrucciones SIMD para cargar y almacenar bloques de memoria más grandes.

Si bien también hay instrucciones SIMD para matemáticas de enteros, son menos comunes (por ejemplo, SEE las introdujo en una versión posterior a las versiones flotantes) y, a menudo, menos sofisticadas. Mi conjetura es que (su compilación de) NumPy no tiene implementaciones SIMD de las operaciones que son más lentas para usted. Alternativamente, las operaciones de enteros pueden no estar tan optimizadas: los flotadores se usan en muchas aplicaciones fáciles de vectorizar cuyo rendimiento importa mucho (por ejemplo, en / decodificación / imagen / medios de video), por lo que pueden estar más optimizados.