Nueva descripción de @ezyang :
El trabajo está en progreso en https://github.com/Roger-luo/pytorch-complex
Así es como se verá el flujo de trabajo en el estado estable.
PyTorch contendrá API de forma nativa para hacer referencia al tipo de d complejo, pero no harán nada de forma predeterminada. PyTorch define torch.complex64 y torch.complex128 en referencia a tensores complejos. Sin embargo, si intenta construir un tensor de esta manera, de forma predeterminada, PyTorch generará un error:
>>> torch.zeros({2,2}, dtype=torch.complex64)
RuntimeError: complex64 not supported by PyTorch
@ezyang proporcionó un parche que agrega estos dtypes a PyTorch. https://github.com/pytorch/pytorch/pull/11173
A mediano plazo, fusionaremos la compatibilidad con la funcionalidad básica (como la asignación de un tensor de ceros) para que PyTorch la admita de forma nativa. Un indicador razonable de lo que el soporte es "básico" es el soporte nativo de PyTorch para los medios tensores de CPU (que están extremadamente empobrecidos).
PyTorch publica una interfaz para registrar una implementación de tensores complejos. La implementación hereda de la clase TypeDefault (https://github.com/pytorch/pytorch/pull/11013) y anulará los métodos de esta clase para definir implementaciones de funciones para las que tenemos implementaciones complejas. Se verá algo como esto:
struct CPUComplexFloatType final : public TypeDefault {
virtual Tensor add(const Tensor & self, const Tensor & other, Scalar alpha=1) const override {
// Your implementation of add for complex tensors
}
// ...
}
Esta clase anulará exactamente los tipos que se admiten para complejo; todas las demás implementaciones son proporcionadas por TypeDefault y generarán un error de forma predeterminada.
Habrá una lista canónica de métodos admitidos en Type (la interfaz general) como un archivo generado automáticamente que se registra en el repositorio fuente de PyTorch; comunicaremos los cambios de la API mediante diferencias a este archivo. En general, los métodos están en correspondencia uno a uno con sus nombres correspondientes en la interfaz de PyTorch.
En general, cuando utiliza una operación que aún no ha implementado,
ADVERTENCIA: Tenemos la intención de refactorizar Type en un nuevo sistema que también admita el registro abierto de nuevas operaciones (esto obviamente no funciona si tiene una sola superclase que define todos los métodos que posiblemente desee admitir). Por lo tanto, trate de no apegarse demasiado a la estrategia de implementación particular de escribir Type como una subclase.
Para publicar solo operaciones nuevas y complejas, utilizará la API de extensión de C++. La API de extensión de C++ está documentada en https://pytorch.org/tutorials/advanced/cpp_extension.html Esencialmente, puede escribir una función de C++ como:
at::Tensor imag(at::Tensor z) {
...
}
Y luego, la API de extensión de C++ generará un enlace de Python para que invoque esta función desde Python.
Algunas operaciones serán "fáciles" de integrar en PyTorch tal como existe hoy. Por ejemplo, para la implementación de operaciones binarias, probablemente tenga más sentido extender add_kernel en BinaryOpsKernel.cpp para que distribuya tipos complejos (y luego lo obtenga gratis, porque std::complex implementa la adición). Siempre que estos parches sean pequeños y autónomos, prometemos fusionarlos en el momento oportuno.
SIEMPRE debería ser posible desbloquear, simplemente escribiendo una anulación en Tipo en lugar de usar la infraestructura existente, y copiando y pegando liberalmente. ¡Pero evitémoslo cuando es fácil!
Autograd. Siempre que esté trabajando en operaciones que ya tienen fórmulas derivadas definidas para ellas, obtendrá "automáticamente" soporte de graduación automática, siempre que implemente soporte complejo para todas las funciones constituyentes que se invocan en la implementación inversa de derivadas.yaml .
En algunos casos, es posible que necesitemos ajustar las fórmulas de autograduación para que funcionen con números complejos; por ejemplo, el gradiente de 'abs' no es 'grad'. self.sign()'. En estos casos, todo lo que tenemos que hacer es cambiar la fórmula de autograduación de 'abs' a 'abs_backward', que es una función que se puede anular.
Para la retropropagación valorada compleja general, hay algunas referencias:
Generalmente, no necesitaremos modificar el autogrado ya que en la mayoría de los casos solo calculamos las derivadas de una función de valor real (la pérdida).
Muchas de las piezas necesarias ya están en su lugar, pero no se ensamblan de manera integral. Esto es lo que hay que hacer.
Plan de integración a corto plazo. Estas operaciones son "fáciles" de implementar, por lo que debemos incluirlas en PyTorch lo antes posible.
Implementación del núcleo:
TODO: generar una lista basada en https://github.com/Roger-luo/TH/blob/master/ChangeLog.md
Otras tareas complejas relacionadas:
Comentario original de @PhilippPelz
Me preguntaba si hay interés en incorporar tensores complejos en pytorch.
Para soporte de CPU hay ztorch y escribí z-cutorch (https://github.com/PhilippPelz/z-cutorch) hace un tiempo. Es una bifurcación de cutorch antes de la refactorización de CudaHalfTensor (todavía no tengo el hardware).
Si no es demasiado trabajo, me gustaría integrarlo lentamente con pytorch. Estoy usando matplotlib para trazar a través de fb.ptyhon y resulta un gran dolor cada vez que reinstalo mi sistema (compilando todas las dependencias), además parece que pytorch funcionará pronto en Windows, en el que se ejecuta una de mis PC experimentales.
También necesitaría gradientes complejos, por lo que tarde o temprano también tocaría autograd.
Si bien tf admite tensores complejos per se, parece que muchas operaciones aún no lo admiten (https://github.com/tensorflow/tensorflow/issues/2255), además parece un poco pesado para mis propósitos.
Tal vez alguien podría decir algunas palabras sobre cómo y por dónde empezar con esto, si es una buena idea.
Creo que estaríamos interesados en agregar un soporte opcional para tensores complejos. La mejor manera sería bifurcar y trabajar en las bibliotecas C en torch/lib
. Esto debería estar libre de conflictos con el maestro, por lo que puede hacerlo durante mucho tiempo. Una vez que tenga las bibliotecas en un estado utilizable, puede comenzar a escribir los enlaces, y aquí es donde podemos brindarle orientación sobre cómo evitar conflictos en ese momento.
Tengo TH con compilación de tipos complejos. ¿Qué necesito agregar para la integración de python?
@PhilippPelz , ¿te refieres a: https://github.com/facebook/ztorch/tree/master/lib/THZ ? ¿O construiste tu propia bifurcación de TH que permite tipos complejos?
@killeent tiene algunas notas sobre cómo TH está vinculado a Python, puede compartirlas.
En general, para obtener tensores complejos, prefiero THZ, ya que tiene pruebas, etc.
Sin embargo, construir un backend de CUDA para tensores complejos es un esfuerzo bastante grande, ni siquiera hemos comenzado con eso.
Escribí z-cutorch (https://github.com/PhilippPelz/z-cutorch) hace un tiempo. Es una bifurcación de cutorch antes de la refactorización de CudaHalfTensor (todavía no tengo el hardware).
Esto es genial. Supongo que ya has hecho un gran esfuerzo en esa dirección :)
@soumith Hice una bifurcación de TH con tipos complejos. Básicamente, un THGenerateComplexTypes.h + agregó BLAS + LAPACK rutinas, el resto fue casi gratis. Parecía mucho menos trabajo para mí que verificar qué partes de THZ son compatibles y luego copiar y pegar.
Estoy atascado compilando THPP en este momento, descifrando mensajes del compilador como
/home/philipp/projects/pytorch/torch/lib/tmp_install/include/TH/generic/THBlas.h:6:40: error: se esperaba ',' o '...' antes del token '*'
TH_API void THBlas_(swap)(long n, real *, long incx, real *, long incy);
es un poco complicado.
Agradecería ayuda sobre cómo habilitar la integración de python. El backend de CUDA debe ser principalmente copiar y pegar de z-cutorch.
@PhilippPelz aquí hay algunas notas sobre PyTorch wraps TH: https://gist.github.com/killeent/4675635b40b61a45cac2f95a285ce3c0
@killeent gracias, parece muy útil. lib/build_all.sh ahora se está compilando, creo que puedo mirar el directorio csrc.
Esto ahora se ejecuta:
importar antorcha como th
importar numpy como np
a = np.matriz([1+1j,2+2j])
b = np.matriz([3+3j,4+4j])
ath = th.from_numpy(a)
bth = th.from_numpy(b)
ath_cuda = ath.cuda()
ath_cuda += bth.cuda()
ath = ath_cuda.cpu()
imprimir (ath. numpy ())
Fuera: [ 4.+4.j 6.+6.j]
junto con la mayoría de las funciones matemáticas.
Agregaré funciones de conveniencia y ffts en las próximas semanas. Supongo que debe haber pruebas para todo antes de poder fusionar esto. Si conoce a alguien más que esté interesado en tensores complejos y esté dispuesto a contribuir a escribir las pruebas, sería increíble. Este artículo me viene a la mente: Deep Complex Networks , tal vez a esos tipos les interese.
No tendré tiempo para escribir todas las pruebas por mi cuenta.
@PhilippPelz Gracias por sus comentarios. Estoy revisando tu implementación. Y en primer lugar, no estoy seguro acerca de su implementación ger
. Algunas funciones blas complejas no están incluidas en su THBlas.c como usted definió GER como zger_
y cger_
en los encabezados generados, pero no hay una función blas con cger_ en el genérico/THBlas.c . Sin embargo, puedo usar tu gemv y algunas otras funciones. Y en mi opinión, ¿quizás deberías agregar .gch a .gitignore? ¿Has empujado todas tus extensiones a tu horquilla? Puedo hacer una solicitud de extracción a su maestro en función de su implementación primero.
Y para DOT
supongo que tal vez para vectores complejos, ¿las rutinas dotc
para punto son más comunes?
Y sí, si solo usar real
será más fácil de implementar, me sentía extraño cuando real
es en realidad un complejo...
Y para las pruebas, no vi ninguna prueba anterior para TH. ¿Dónde debo escribir esas pruebas? o simplemente escribimos algunas pruebas de python
Sí, lo siento, veo que es posible que no haya empujado todo lo que se necesita. El lunes lo vuelvo a consultar. Faltan algunas declaraciones, p. zger y cger
Para DOT estoy usando cdotc y zdotc, parece que faltan, actualizaré la próxima semana.
Consulte con los mantenedores de pytorch qué nombres prefieren de verdad. Me gusta más tu versión, solo que todavía no me esforcé.
Sí, pruebas de Python para las matemáticas. Debe cambiarse fácilmente para que la mayoría de las funciones también incluyan verificaciones de números compelx.
¡Genial que también estés investigando esto!
Ok, hice algunos cambios. Las rutinas TH blas ahora están ahí para complejos
@PhilippPelz Acabo de hacer una solicitud de extracción en su repositorio. Y para capas lineales complejas y algunos otros operadores. podría haber muchas operaciones hermitianas (como bp para una capa lineal compleja). ¿Quizás agregar alguna función para un tensor? ¿Has comprobado la parte de THNN?
Sí hermitian es útil. cuda fft está funcionando ahora. cpu fft podría envolverse desde numpy. Todavía no he tocado THNN o THCUNN.
@PhilippPelz He agregado un hermitiano simple en PR. Y podrías revisarlo. Entonces podríamos ver si esos cambios son adecuados y pasar al siguiente paso. ¡Gracias! PD. parece que te perdiste algunos encabezados, también corrijo eso y algunas otras advertencias. Para una función compleja con salida real, ¿debemos devolver un tensor real en lugar de un tensor complejo? Implementé métodos de copia entre tipos complejos y reales, por lo que es posible.
Volveré a basar todos los compromisos después de su revisión.
@PhilippPelz Hola, estoy bastante confundido acerca de la parte THPP
que implementaste. ¿Por qué depende del empuje en Traits.hpp
? Esto causará un error al compilar sin cuda. ¿Es posible usar solo comoTraits.hpp
? No lo he descifrado. ¿Tal vez podrías ofrecer algunas pistas?
@ Roger-luo Sí, también tengo algunos problemas con eso en otros lugares. Los tipos complejos que estamos usando deben ser de complex.h o std::complex. Dado que THPP es el contenedor de C++, tal vez std::complex sea más apropiado. ¿Puedes cambiar eso?
Thrust también está causando problemas exactamente por la misma razón cuando intenta crear extensiones cffi. En este momento estoy haciendo una solución alternativa, pero la forma adecuada sería cambiar el tipo complejo a cuFloatComplex/cuDoubleComplex en THC. para que el compilador cffi no se queje. Solo quiero continuar con la investigación ahora mismo, esto me está quitando demasiado tiempo :( . Si tiene tiempo, hágalo.
Además, crear una extensión cffi con llamadas de kernel personalizadas es bastante engorroso, porque uno siempre necesita crear una biblioteca adicional compilada con nvcc, que luego se vincula a un contenedor cffi. Supongo que no hay otra manera. Se podría usar cffi en modo ABI, pero el sitio web dice "El modo API en su lugar compila un contenedor CPython C que invoca directamente la función de destino. Es, comparativamente, mucho más rápido (y funciona mejor que libffi)".
@PhilippPelz tal vez reinterpret_cast
podría ser una solución. Supongo que debería cambiarse a cuComplex
y usar reinterpret_cast
en THPP. Voy a probar primero...
Sí, supongo que no hay otra forma que reinterpret_cast si quieres que THPP construya también sin cuda instalado.
@PhilippPelz Me gustaría ayudar. ¿Hay alguna lista de tareas pendientes en alguna parte?
THNN y THCUNN deben estar habilitados para tipos complejos. ¿Puedes coordinar con @roger-luo? Además, si nuestro objetivo es la integración con el maestro, las pruebas unitarias deben escribirse para todos los métodos complejos.
@elbamos La mayor parte del trabajo en THNN
consistirá en implementar nuevos métodos complejos de retropropagación para cada capa existente. Hay un WIP PR en la bifurcación de Philipp. He enumerado algunas referencias.
@apaszke @soumith @PhilippPelz Y hay dos preguntas:
¿Alguien sabe por qué hay otro archivo GenerateXXXTypes.h
en THS
? Se ve igual que los de TH
.
¿Para qué sirve el siguiente código en byte_order.cpp
?
void THP_decodeFloatBuffer(float* dst, const uint8_t* src, THPByteOrder order, size_t len)
{
for (size_t i = 0; i < len; i++) {
union { uint32_t x; float f; };
x = (order == THP_BIG_ENDIAN ? decodeUInt32BE(src) : decodeUInt32LE(src));
dst[i] = f;
src += sizeof(float);
}
}
void THP_decodeDoubleBuffer(double* dst, const uint8_t* src, THPByteOrder order, size_t len)
{
for (size_t i = 0; i < len; i++) {
union { uint64_t x; double d; };
x = (order == THP_BIG_ENDIAN ? decodeUInt64BE(src) : decodeUInt64LE(src));
dst[i] = d;
src += sizeof(double);
}
}
¿Alguna sugerencia sobre la implementación de su versión compleja relacionada? No estoy seguro si la siguiente implementación es correcta...
void THP_decodeZFloatBuffer(std::complex<float>* dst, const uint8_t* src, THPByteOrder order, size_t len)
{
for (size_t i = 0; i < len; i++) {
union { uint64_t x; std::complex<float> cf;};
x = (order == THP_BIG_ENDIAN ? decodeUInt64BE(src) : decodeUInt64LE(src));
dst[i] = cf;
src += sizeof(std::complex<float>);
}
}
void THP_decodeDoubleBuffer(std::complex<double>* dst, const uint8_t* src, THPByteOrder order, size_t len)
{
for (size_t i = 0; i < len; i++) {
union { uint128_t x; std::complex<double> df;};
x = (order == THP_BIG_ENDIAN ? decodeUInt128BE(src) : decodeUInt128LE(src));
dst[i] = df;
src += sizeof(std::complex<double>);
}
}
El decodeUInt128XE
anterior se declara como
static inline uint128_t decodeUInt128LE(const uint8_t *data) {
return (((uint128_t)data[ 0])<< 0) | (((uint128_t)data[ 1])<< 8)|
(((uint128_t)data[ 2])<< 16) | (((uint128_t)data[ 3])<< 24)|
(((uint128_t)data[ 4])<< 32) | (((uint128_t)data[ 5])<< 40)|
(((uint128_t)data[ 6])<< 48) | (((uint128_t)data[ 7])<< 56)|
(((uint128_t)data[ 8])<< 64) | (((uint128_t)data[ 9])<< 72)|
(((uint128_t)data[10])<< 80) | (((uint128_t)data[11])<< 88)|
(((uint128_t)data[12])<< 96) | (((uint128_t)data[13])<<104)|
(((uint128_t)data[14])<<112) | (((uint128_t)data[15])<<120);
}
static inline uint128_t decodeUInt128BE(const uint8_t *data) {
return (((uint128_t)data[15])<< 0) | (((uint128_t)data[14])<< 8)|
(((uint128_t)data[13])<< 16) | (((uint128_t)data[12])<< 24)|
(((uint128_t)data[11])<< 32) | (((uint128_t)data[10])<< 40)|
(((uint128_t)data[ 9])<< 48) | (((uint128_t)data[ 8])<< 56)|
(((uint128_t)data[ 7])<< 64) | (((uint128_t)data[ 6])<< 72)|
(((uint128_t)data[ 5])<< 80) | (((uint128_t)data[ 4])<< 88)|
(((uint128_t)data[ 3])<< 96) | (((uint128_t)data[ 2])<<104)|
(((uint128_t)data[ 1])<<112) | (((uint128_t)data[ 0])<<120);
}
Actualmente uso std::complex<T>
en lugar de T _Complex
en THPP
. No estoy seguro de que esto pueda ser usado por Python todavía. O solo el tipo c T _Complex
se puede usar para python. Así que aquí el tipo de dst es std::complex<T>
.
Y si estoy en lo correcto para esta implementación, probablemente necesitemos una implementación uint128_t
, como https://github.com/calccrypto/uint128_t ? Dado que parece que no todos los compiladores admiten enteros de 128 bits (gcc tiene int128_t y uint128_t).
@PhilippPelz noté que su bifurcación no tiene problemas habilitados. ¿Cuál es el estado de su proyecto? Estoy un poco molesto porque los tensores complejos no están en la hoja de ruta para pytorch
@el3ment He agregado un backend complejo para CPU https://github.com/pytorch/pytorch/pull/4899 Pero aún no se ha revisado... Y no he recibido ningún comentario para mi PR, así que recurrí a usar el lenguaje de programación Julia recientemente...
Le envié un correo electrónico a @PhilippPelz la última vez, supongo que su repositorio todavía está en v0.1 y está ocupado con la tesis hasta septiembre. Y estaba trabajando en el nuevo backend CUDA de v0.3, pero no tengo tiempo para terminar todos estos enlaces solo. Las funciones map/reduce son diferentes de v0.1 con algunas optimizaciones, pero no se pueden convertir de manera trivial para admitir números complejos. Sería feliz si hay alguien que esté dispuesto a ayudar...
Estoy dispuesto a ayudar.
El 10 de abril de 2018, a las 22:52, Rogerluo [email protected] escribió:
@el3ment He agregado un backend complejo para CPU #4899
Le envié un correo electrónico a @PhilippPelz la última vez, supongo que su repositorio todavía está en v0.1 y está ocupado con la tesis hasta septiembre. Y estaba trabajando en el nuevo backend CUDA de v0.3, pero no tengo tiempo para terminar todos estos enlaces solo. Las funciones map/reduce son diferentes de v0.1 con algunas optimizaciones, pero no se pueden convertir de manera trivial para admitir números complejos. Sería feliz si hay alguien que esté dispuesto a ayudar...
—
Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.
@elbamos genial, parece que el equipo de pytorch prefiere una implementación separada. Actualizaré mi bifurcación más tarde para las otras partes más adelante. Pero realmente no tengo tiempo para esto y supongo que deberíamos comenzar a trabajar en ello cuando haya un plan del equipo de pytorch porque sería una gran extensión para pytorch.
Hola, mi código está en algún compromiso después de v0.2
Había visto que había un refactor bastante grande moviendo todo el código de tensor a Aten. Esto significa que uno no puede fusionar fácilmente mi bifurcación en la versión actual y podría haber más trabajo involucrado.
Todavía estoy escribiendo mi doctorado, pero planeaba esperar a 0.4 de todos modos hasta que se publique la fusión de Variable y Tensor. Me temo que podría haber demasiada refactorización para ponerse al día si uno lo hace antes.
@elbamos , si quieres, puedes comenzar a agregar cosas a mi bifurcación, las fusionaré. En tu lugar, simplemente implementaría lo que necesitas para cualquier proyecto que estés haciendo. TH(CU)NN es una interfaz bastante grande y sería una gran carga de trabajo.
@el3ment No tengo tiempo para trabajar en los problemas de otros. Sin embargo, fusionaré cosas si necesita implementar algo que no está allí.
Si solo desea algo que funcione con números complejos de forma inmediata, le recomiendo tensorflow.
También ayudaré si hay problemas de compilación.
Si continúo con el postdoctorado, en algún momento transferiré todo esto a la versión actual. Es realmente triste que facebook no quiera apoyar esto. :((
@PhilippPelz De acuerdo, es realmente triste y, en realidad, tensorflow no es compatible con todos los operadores de la física cuántica ... Comencé a usar Julia y abandoné Python.
@ Roger-luo interesante, ¿estás usando un paquete julia específico o es todo un código escrito por ti mismo?
@PhilippPelz Estoy desarrollando un kit de herramientas cuántico de muchos cuerpos en Julia (desde PyTorch PR), incluye una implementación de red neuronal compleja/real basada en algunos artículos anteriores sobre redes neuronales complejas, y descubrí que es muy fácil de desarrollar con Julia's metaprogramación. Actualmente solo lo puse en QMTK.jl , todavía está trabajando en progreso y no he terminado todo lo que quiero. PyTorch me inspira mucho, pero lo siento mucho por el soporte complejo...
Pero tengo planes para separarlo en un paquete único de red neuronal en el futuro (simplemente no quiero mantener varios repositorios en este momento). Y habrá más personas que se unan al desarrollo desde el Instituto de Física, CAS. Aceptaré PR después de su primera versión etiquetada (que será en unas pocas semanas).
Puedes verlo si estás interesado en su desarrollo.
Sin embargo, si el equipo de PyTorch todavía tiene planes para un soporte complejo en el futuro, estaré dispuesto a ayudar.
Genial, estaré al pendiente!
Hola chicos, siento mucho que no hayamos respondido sobre este problema desde que se abrió.
Aquí hay dos hechos:
Desde que se abrió este problema en 2017, han cambiado algunas cosas importantes que pueden simplificar un poco la implementación de soporte complejo. La primera es que ahora tenemos ATen, una biblioteca C++ ergonómica para manipular tensores. Esto significa que no tiene que copiar y pegar franjas gigantes de código TH/THC y esperar que haya hecho todo el recuento manual correctamente, puede escribir código C++ como si fuera Python y se ejecutará rápidamente. En segundo lugar, estamos trabajando en una nueva versión de ATen, llamada C10, que se toma mucho más en serio tener backends abiertos que ATen (que es algo cerrado), lo que debería facilitar el trabajo en soporte complejo, ya que no No implica bifurcar PyTorch, simplemente agregando un nuevo directorio de código.
Entonces, @Roger-luo y @PhilippPelz , nos encantaría contar con su ayuda para hacer realidad el backend complejo, pero realmente nos gustaría encontrar una manera de hacerlo que nos ayude a mantenerlo de manera sostenible en el futuro. Háganos saber lo que piensas.
@ezyang Si no tiene mano de obra, podría intentar mantener la parte del tensor complejo en el futuro, acabo de comenzar mi doctorado (y este es mi año sabático en realidad) y, por lo tanto, no tendré el problema de escribir mi tesis en al menos los últimos años. Pero realmente no puedo seguir contribuyendo sin recibir comentarios del equipo de pytorch. Creo que debería haber una hoja de ruta para esta gran extensión. Y podríamos agregar soporte complejo sin problemas para que sus muchachos no necesiten revisar un gran PR y facilitará los esfuerzos de los desarrolladores en el seguimiento de la rama maestra.
En primer lugar, creo que el principal problema del soporte complejo sería la parte de CUDA. Es bastante fácil admitir la parte de la CPU con ATen o cualquier otra biblioteca, puedo reescribir la parte de la CPU en solo unos días si hay algún comentario. Hay algunos problemas que podrían preocuparme por parte de CUDA, y creo que esto podría conducir a dos enfoques diferentes:
float2
, etc. para simular un único valor complejo como lo hace cuComplex
en la parte de CUDA.FloatTensor
y DoubleTensor
existentes para simular un tensor complejo en la parte C++ de ATen.El motivo del segundo enfoque es que en THC
, pytorch usa algunos trucos para acelerar las operaciones de mapa/reducción y no es adecuado para cuComplex
trivialmente porque cuComplex
es en realidad float2
, pero las funciones __shfl_xxx
no admiten de forma nativa float2
. No estoy seguro de cómo simular de manera eficiente dicha función por float2
en este momento.
El segundo enfoque sería más fácil porque ahora no necesitamos preocuparnos por el hardware, y podemos hacer que nuestra nueva extensión compleja funcione en dispositivos antiguos mucho más fácilmente. Sin embargo, esto podría causar cierta sobrecarga debido a la dirección de memoria no contigua.
Además, descubrí que para integrar números complejos en ATen, podríamos tener que manejar cuatro tipos diferentes que en realidad son iguales en el hardware: std::complex
, thrust::complex
, cuComplex
, float2
que a veces puede ser peligroso. (de hecho, encontré este problema el año pasado, y reinterpreter_cast
fue la solución).
Sin embargo, personalmente preferiría escribir todo más nativo.
Y creo que probablemente necesitemos un marco de tiempo o una hoja de ruta, y podemos recoger cada pequeña parte y trabajar juntos, así que no tendré que rastrear el maestro yo mismo, lo cual es totalmente imposible...
hubo un ChangeLog cuando estaba tratando de implementar el backend de la CPU, clasifiqué las funciones que deben modificarse para números complejos en el registro. Podríamos escribir un mapa de ruta basado en este registro.
Además, como me acaban de rechazar la visa (por parte de Australia), tengo que empezar un año sabático, si necesitas que alguien siga trabajando en esto, podría solicitar una pasantía.
Pensé mucho en esto durante el último día. Es un poco triste que no pudimos fusionar el esfuerzo de Roger tal como está, pero pensé para mis adentros
"¿Cómo podemos desarrollar un soporte de Tensor complejo y mantener bajos los gastos generales de mantenimiento?"
Esto es lo que estoy presentando como un plan efectivo del objetivo anterior:
sparse
. Agregar un tipo fundamental provoca una gran cantidad de gastos generales de mantenimiento y cambios transversales. La sobrecarga de mantenimiento no se trata de "¿quién mantiene los bits complejos?", sino más bien de "ahora todos los desarrolladores principales deben ser conscientes de este tipo complejo al realizar cambios fundamentales, cualquier cambio de ATen, etc."torch.stack([real1 * real2 - imag1 * imag2, real1 * imag2 + imag1 * real2], dim = -1)
donde real1 = input1[:, :, :, ..., 0]
Tiene que ser [Tensor Shape x 2] ya que BLAS, cublas y MAGMA esperan sus propios tipos complejos que sean compatibles con bytes para float2. Además, las llamadas de blas, cublas y magma no se pueden manejar en el nivel de python.
No creo que sea solo el 20% para la multiplicación compleja, ¿no tienes 4 operaciones de copia completa además de los cálculos para la parte real e imagen?
De todos modos, todavía estaría feliz si no tuviera que fusionar los cambios del maestro continuamente.
De acuerdo con @PhilippPelz , podríamos perder mucho rendimiento ya que perderemos el soporte complejo de BLAS, cublas y MAGMA. Pero no estoy seguro de eso. Sin embargo, para ser claros, el tensor complejo es algo completamente diferente del tensor disperso , la mayoría de las bibliotecas como scipy.sparse
y el SparseArrays
de Julia tratan el arreglo disperso como una composición de arreglos multidimensionales fundamentales. Pero nadie trata una matriz multidimensional con un tipo complejo mediante dos matrices reales compuestas ... (nadie aquí me refiero a tensorflow, arrayfire, numpy y Julia). Aunque en MXNet, la FFT se logra mediante una composición de dos tensores reales, de hecho, no admiten complejos... Parece que tensorflow implementó un tipo de datos como un envoltorio alrededor de diferentes tipos de redes, incluidos complex64
y complex128
ver tipos.proto
En primer lugar, las funciones basadas en elementos (llamadas a funciones mapear/reducir) no tendrán una gran pérdida de rendimiento (al menos, la memoria para estas operaciones será contigua). Pero creo que primero deberíamos intentar comparar algunas funciones de BLAS, para ver si una composición de FloatTensor
tiene un rendimiento similar con Complex64Tensor
en GPU, y cuánto perderemos en rendimiento con una proyecto de implementación, como:
gemm
gemv
Un tensor complejo compuesto sería algo parecido (o simplemente use shared_ptr
):
class ComplexTensor {
FloatTensor *real;
FloatTensor *imag;
};
Sin embargo, como mencioné en la desventaja del primer enfoque, funciones como __shfl_xxx
también parecen un obstáculo si queremos hacer esto de forma más nativa.
actualmente torch.fft
devuelve un solo tensor flotante de forma [dim1, ..., dimN, 2]
@ezyang, ¿cuál es el plazo para el lanzamiento del C10? Eso suena como un punto muy razonable para comenzar a admitir complejos en la rama maestra.
@PhilippPelz Definitivamente no para 0.4. Estamos apuntando internamente a junio, espero que no sea demasiado tiempo de espera.
@ezyang mencionaste a June, ¿conseguiste agregar soporte para números complejos a PyTorch?
Creo que se refería a C10, no a soporte complejo. C10 hará que agregar complejos sea más fácil. Así lo entendí.
Sí, C10 tendrá registro abierto tanto de tipos como de funciones de Tensor. Por lo tanto, agregar un tipo complejo como un paquete separado será mucho más fácil.
¿Hay algún ETA en números complejos? ¿"Mucho más fácil" significa "probablemente se hará rápidamente"?
@themightyoarfish por mucho más fácil, quiero decir que no seremos bloqueados en lo que se puede enviar a pytorch master. No hemos establecido una ETA. Examinaré el trabajo una vez que tengamos un registro abierto en PyTorch.
@soumith , ¿todavía necesita gente para trabajar en este (número complejo)? ¿El equipo de PyTorch admitirá números complejos? Puedo dedicar algún tiempo a trabajar en esto si lo desea en septiembre, ya que mantendré QuCumber (utilizará mucho el número complejo)
@Roger-luo sí. Quería comunicarme con usted una vez que tengamos el registro abierto disponible en el backend de PyTorch, y podamos resolver los detalles.
@ezyang , ¿tendremos registro de tipo abierto para septiembre?
@soumith Genial, a su servicio.
Podemos hacer que suceda. (No tendremos el nuevo sistema "completo" implementado, pero siempre que configuremos las cosas para que sea refactorizable, podemos seguir moviéndolo a medida que ocurren nuevos desarrollos. Será un buen caso de prueba para el nuevo abierto registro. Puedo asegurarme de que esto suceda.)
@ezyang alguna nota por ahora? Podría leerlo antes de trabajar en él. Parece que las cosas han cambiado mucho desde la última vez.
@Roger-luo @PhilippPelz También me gustaría ayudarlo con la implementación de tensores complejos. También lo necesito para mis investigaciones de doctorado..
@alexgomezalanis tal vez podríamos tener un canal para discutir en la holgura, acabo de crear una llamada de canal #complex-numbers
. Pero no empezaré a trabajar en él hasta septiembre (todavía necesito trabajar en parte de mi código de Julia...)
Por cierto, parece que ha cambiado mucho desde la última vez. Usaré un poco de tiempo para ponerme al día antes de ponerle las manos encima.
@alexgomezalanis No puedo. primero debe unirse al espacio de trabajo de pytorch en holgura. No puedo encontrarte. Envíe un correo electrónico a la dirección: [email protected] para obtener una invitación.
@Roger-luo @alexgomezalanis Genial volver a ver la vida en el tema del tensor complejo. Puedo ofrecerme para participar también, pero siendo realistas, esto no sucederá hasta finales de septiembre o principios de octubre. En cuanto a algunos comentaristas sobre este tema, el soporte de tensor complejo sería muy útil para mi proyecto de doctorado.
También estaba tratando de salvar mi investigación el año pasado 😏... pero ahora solo quiero revivir mi viejo código 1w+ loc. 🤣 ¡hablemos en Slack!
:) Sí, hablemos en Slack. Acabo de encontrar la invitación en la carpeta de correo.
El complemento de trabajo en progreso (solo para CPU a corto plazo) está aquí: https://github.com/Roger-luo/pytorch-complex
Por favor, siéntase libre de darme un problema y relaciones públicas.
He publicado las notas sobre cómo se llevará a cabo la implementación compleja en la parte superior de este número.
Recientemente comencé a usar PyTorch y me encanta, es mucho más agradable de usar que TensorFlow. Sin embargo, el soporte de tensores complejos es bastante crítico para mi investigación (redes neuronales ópticas). ¿Todavía se está trabajando activamente en esto? Si es así, ¿alguien sabe un marco de tiempo (flojo) para el soporte de tensor complejo?
Estaría feliz de ayudar a trabajar en esto donde pueda, pero soy relativamente nuevo en PyTorch, por lo que todavía no tengo una buena idea de qué tan grande es la tarea de esta característica. Algunos de mis compañeros de laboratorio también han expresado un gran interés en el soporte de tensor complejo (en física, agregar esto podría hacer que Torch sea casi un reemplazo acelerado por GPU para NumPy) y podrían estar dispuestos a ayudar si eso significa obtener soporte complejo en el futuro cercano.
Hola @bencbartlett
Todavía estoy tratando de trabajar en ello lentamente... pero actualmente también soy solo un estudiante (con una situación bastante inestable), lo que significa que no puedo trabajar en esto a tiempo completo, sino solo en mi tiempo libre. (Implementé mi código relacionado con la investigación en Julia del año pasado, lo que significa que solo nuestro paquete heredado necesita un mejor soporte de números complejos de la antorcha).
Si el número complejo es crucial para usted y es urgente tenerlo en la antorcha, le sugiero que intente esto:
https://github.com/PIQuIL/QuCumber/blob/master/qucumber/utils/cplx.py
Es super lento... pero al menos funciona. O tenía una versión C al viejo estilo TH.
Este no será un proyecto pequeño que se puede hacer en unos pocos días. Por lo tanto, no puedo garantizar ningún marco de tiempo específico para un soporte funcional completo con valor complejo en CPU o CUDA.
Sin embargo, me encantaría ayudarlo a trabajar conmigo en esto. Le sugiero que comience tratando de resolver los problemas que publiqué en el repositorio de extensiones. Y no dude en preguntarme a través de Slack, correo electrónico o problema si tiene preguntas (ya que aún no hay muchos documentos).
Desafortunadamente, todavía no tengo acceso a PyTorch Slack. (Envié un correo electrónico dos veces pidiendo una invitación, pero no he recibido respuesta). ¿Alguien podría invitarme? ([email protected])
@Roger-luo Definitivamente revisaré tu bifurcación, pero no puedo prometer que seré de mucha ayuda: mi C ++ está oxidado y, como señalaste, es difícil encontrar tiempo para trabajar en esto como un estudiante. Las utilidades de QuCumber son agradables, pero desafortunadamente no serían muy útiles para mí: hasta que los tensores complejos sean compatibles con GPU o con autograd y torch.nn, no brindan mucha utilidad por encima de lo que puede ofrecer NumPy.
@soumith @ezyang ¡Sería genial recibir más atención sobre esto por parte del equipo de PyTorch! El soporte complejo parece ser una característica importante para una biblioteca general de tensores, es prácticamente esencial en física y específicamente dentro de ML en los últimos años, ha habido un interés creciente en modelos de valores complejos.
El enfoque de @bencbartlett QuCumber se puede usar en GPU con AD... es simplemente súper lento... Quiero decir, si solo quieres ese AD, es posible que puedas usarlo.
Sí, hablando francamente, estoy usando una versión ligeramente modificada de https://github.com/FluxML/Flux.jl y mi propio paquete en Julia para investigación (también necesito AD complejo en GPU con tensores en algunas situaciones ). El paquete de AD source2source Zygote.jl puede hacer AD en tensores complejos, pero se encuentra en una etapa muy temprana que puede tener fallas de segmento. El ecosistema aún no es tan estable en comparación con la antorcha, a veces tengo que piratear un poco esas implementaciones para uso propio... Pero básicamente funciona para lo que necesito para la investigación en física cuántica. También puedo tener tensores complejos en la GPU.
No creo que se necesite soporte de valor complejo para torch.nn
, es posible que solo necesitemos agregar algunas definiciones para autograd
una vez que el tensor complejo sea funcional, porque cosas como las capas lineales pueden permanecer igual . Y es posible que algunas funciones de activación no tengan una expansión estándar en el espacio de Hilbert... (Puede consultar la publicación del blog de mi colaborador @GiggleLiu )
Para la extensión pytorch-complex, no estoy seguro de cuándo podremos obtener soporte completo con AD en GPU... esto todavía me parece bastante lejano. Diría que la implementación de la CPU pasará por un período que requiere parches en el árbol principal (por ejemplo, promociones de tipo, compatibilidad con simd, etc.), esto también podría estar relacionado con la próxima implementación de ATen en C++ y deshacerse de TH, etc. y luego podremos agregar operadores para tensores complejos más rápido.
Puedo solicitar pasantías en primavera (sobre las cuales le acabo de preguntar a @ezyang ). Así que podría trabajar en esto a tiempo completo durante varios meses antes de comenzar mi doctorado. Vamos a ver.
Mientras tanto, implementé mi propia versión de la multiplicación compleja. Sin embargo, cuando lo perfilo, sucede que una cantidad sustancial de tiempo se destina a: torch._C_._cuda_isDriverSufficient
¿Tienes alguna idea de por qué? Si conoce una mejor implementación de la multiplicación compleja, hágamelo saber. De alguna manera, mi versión (aunque optimizada para el número de multiplicaciones: 3 en lugar de 4) parece ser relativamente lenta, por ejemplo, irfft del tensor de salida es 10 veces más rápido que mi multiplicación por elementos. ¿Se admite la multiplicación compleja en el nivel C++ de PyTorch?
def complex_mul(x, y, out):
uavc = x[..., 0] * (y[..., 0] + y[..., 1])
out[..., 0] = uavc - (x[..., 0] + x[..., 1]) * y[..., 1]
out[..., 1] = (x[..., 1] - x[..., 0]) * y[..., 0] + uavc
def test_complex_mul_out_tensor(self):
N, C, H, W, I = 128, 3, 32, 32, 2
K = 16 # number of filter banks
repetitions = 1000
dtype = torch.float
if torch.cuda.is_available():
device = torch.device("cuda")
else:
device = torch.device("cpu")
x = torch.randn(N, 1, C, H, W, I, dtype=dtype, device=device)
y = torch.randn(K, C, H, W, I, dtype=dtype, device=device)
start_mul_time = time.time()
out = torch.empty(N, K, C, H, W, I, dtype=dtype, device=device)
for _ in range(repetitions):
complex_mul(x, y, out)
print("multiplication time: ", time.time() - start_mul_time)
Estamos tratando de soportarlo desde C++. ver la publicación en la parte superior. Si puede compilar la extensión, debería funcionar para la multiplicación escalar al menos en este momento...
Su implementación es similar a la que tenemos en QuCumber. Podría llamar a muchos subprocesos de GPU adicionales si no llama al kernel cuda correcto para el número complejo. Y es posible que pierda SIMD si no tiene un backend de C++ como soporte en Python.
Le sugiero que ejecute nvprof
para obtener más detalles.
@Roger-luo @apaszke @soumith Gracias por este hilo por cierto. Implementé un tensor complejo básico pirateado a partir de la subclasificación de torch.Tensor.
Trato la primera mitad como real, la segunda como imaginaria e implementé mis propias operaciones aritméticas básicas y algunas otras que necesito para mi investigación.
Verifiqué contra Tensorflow y numpy. ¡Los gradientes y todas las operaciones que implementé coinciden con sus resultados!
Solo pretende ser un remanente hasta que PT admita completamente tensores complejos.
Características:
pip install pytorch-complex-tensor
¡Gracias @williamFalcon !
¿Alguna actualización de esto? Solo me preguntaba si habrá un plan para integrar el soporte de tipo complejo en pytorch.
Hola, @whmrtm
@ezyang está trabajando en https://github.com/Roger-luo/pytorch-complex/issues/4 O quien esté interesado en esto podría ayudarnos a hacerlo funcionar. Este problema resolverá algunos problemas básicos de transmisión (entonces puede usar muchas funciones después de que se resuelva este). Por favor, siéntase libre de hacer cualquier PR o pedirme que lo agregue como colaborador.
No podré trabajar en nada hasta el verano, tengo que terminar un nuevo lanzamiento para nuestro propio paquete.
Hola, @whmrtm
@ezyang está trabajando en Roger-luo/pytorch-complex#4 O quien esté interesado en esto podría ayudarnos a hacerlo funcionar. Este problema resolverá algunos problemas básicos de transmisión (entonces puede usar muchas funciones después de que se resuelva este). Por favor, siéntase libre de hacer cualquier PR o pedirme que lo agregue como colaborador.
No podré trabajar en nada hasta el verano, tengo que terminar un nuevo lanzamiento para nuestro propio paquete.
Gracias por la actualización, veré qué puedo hacer.
Hola @Roger-luo
¿Puedo acceder al canal de holgura relacionado con el tema de soporte de tensores complejos ([email protected])? Envié un correo electrónico para una invitación, pero no pasó nada todavía. En este momento estoy tratando de averiguar los puntos por donde empezar a contribuir a este problema. Supongo que https://github.com/Roger-luo/pytorch-complex/issues/4 es un punto de entrada actual ahora.
@beconstant sí, ese es el punto de partida, esto debería hacer que funcione alguna función de transmisión, pero no sé por qué arroja un error de promoción de tipo en cuda, estaba funcionando en la CPU. (Aunque no tenemos la intención de admitir cuda en primer lugar, esto provocaría una falla en la compilación)
No puedo enviarte un correo electrónico de invitación (no tengo acceso). Creo que deberías seguir la guía oficial de pytorch para unirte a Slack. Pero siempre podemos discutir en el tema/PR.
@Roger-luo está bien, lo tengo :)
Avísenme si necesitan ayuda. Comenzaré construyendo la versión de pytorch especificada. ¿Algún progreso en pytorch-complex/issues/4 ?
Avísenme si necesitan ayuda. Comenzaré construyendo la versión de pytorch especificada. ¿Algún progreso en pytorch-complex/issues/4 ?
@dylanbespalko Hola, necesito urgentemente que se implemente pytorch en una versión de valor complejo.
Muchas gracias por tus aportes.
Atentamente,
Zellar209
Hola @Zellar209 ,
Tengo la sensación de que @ezyang está trabajando duro en uno de los problemas más importantes ( pytorch-complex/issues/4 ). Tengo un sistema AMD ahora y un sistema Nvidia en 3 semanas que puedo usar para aumentar el soporte de GPU.
Supongo que el problema es que el cambio de promoción del tipo original interrumpe CUDA, siempre que se resuelva ese PR, al menos algunos operadores funcionan en la CPU, todavía no tenemos soporte para CUDA...
En mi humilde opinión, creo que primero deberíamos centrarnos en la CPU y hacer que las cosas funcionen, y luego considerar la GPU.
El soporte solo para CPU está bien. ¿Este tipo de problema de promoción ( pytorch-complex/issues/4 está siendo manejado internamente por fb? ¿Está bien trabajar en él externamente?
Hola @dylanbespalko; Le dije a @Roger-luo que iba a investigarlo (porque probablemente era el mejor ubicado para averiguar cuál es el problema), pero aún no he tenido tiempo de analizarlo. Si desea ver cómo solucionar el problema, estaré encantado de aconsejarle.
Hola @Zellar209 ,
Tengo la sensación de que @ezyang está trabajando duro en uno de los problemas más importantes ( pytorch-complex/issues/4 ). Tengo un sistema AMD ahora y un sistema Nvidia en 3 semanas que puedo usar para aumentar el soporte de GPU.
Sí, no necesito ninguna GPU ahora, estoy usando el sistema MAC. Pero he tenido algunos errores al construir este proyecto.
Hola @Zellar209 , ¿podrías publicar lo que obtienes en el problema de pytorch-complex? Creo que hay algo mal con el nuevo Xcode de Mac, que lo hace difícil de construir. Pero la gente necesitará más mensajes de error para averiguar por qué.
Pregunté sobre el sistema operativo y el mensaje de error, pero no respondió...
Hola @dylanbespalko; Le dije a @Roger-luo que iba a investigarlo (porque probablemente era el mejor ubicado para averiguar cuál es el problema), pero aún no he tenido tiempo de analizarlo. Si desea ver cómo solucionar el problema, estaré encantado de aconsejarle.
Gracias por su pronta respuesta.
construyendo la extensión 'torch_complex.cpp'
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/anaconda3/include -arch x86_64 -I/anaconda3/include -arch x86_64 -I/ anaconda3/lib/python3.6/site-packages/torch/include -I/anaconda3/lib/python3.6/site-packages/torch/include/torch/csrc/api/include -I/anaconda3/lib/python3. 6/site-packages/torch/include/TH -I/anaconda3/lib/python3.6/site-packages/torch/include/THC -I/anaconda3/include/python3.6m -c src/module.cpp -o build/temp.macosx-10.7-x86_64-3.6/src/module.o -g -stdlib=libc++ -std=c++11 -DTORCH_API_INCLUDE_EXTENSION_H -DTORCH_EXTENSION_NAME=cpp
gcc: error: opción de línea de comandos no reconocida '-stdlib=libc++'
En archivo incluido desde src/module. cpp:2 :
En el archivo incluido de src/CPUComplexType.h:60:
src/CPUComplexTypeImpl.h:102:105: advertencia: 'IntList' está en desuso [-Wdeprecated-declarations]
Tensor & CPUComplexType::set_(Tensor & self, Storage source, int64_t storage_offset, tamaños de IntList, pasos de IntList) const {
^
/anaconda3/lib/python3.6/site-packages/torch/include/c10/util/ArrayRef.h:273:7: nota: 'IntList' se ha marcado explícitamente como obsoleto aquí
usando IntList C10_DEPRECATED_USING = ArrayRef
^
En archivo incluido desde src/module. cpp:2 :
En el archivo incluido de src/CPUComplexType.h:60:
src/CPUComplexTypeImpl.h:105:76: error: ningún miembro llamado 'scalarTypeToDataType' en el espacio de nombres 'at'
fuente automática_ = almacenamiento_comprobado(fuente,"fuente",2, DeviceType::CPU, en::scalarTypeToDataType(CPUComplexTypeInfo::scalar_type));
~~~~^
7 advertencias y 2 errores generados.
No puedo arreglarlo. ¡Realmente espero que puedas ayudarme!
Hola chicos,
Gracias por tus comentarios. Creo que puedo pasar la semana investigando esto. Hasta ahora, he compilado el complejo pytorch de @ Roger-luo de la siguiente manera:
@ Zellar209 : Adjunté mis variables de entorno que se ejecutan en macOS 10.13.
Elimine la distribución de pytorch existente de la siguiente manera
conda desinstalar pytorch
antorcha de desinstalación pip
pip desinstalar antorcha # ejecutar este comando dos veces
python setup.py limpio
Elimine la carpeta torch en la carpeta de paquetes del sitio de python, si existe.
Cambie el nombre (o elimine) la carpeta de origen de pytorch anterior (algo se refería a ella).
Instale PyTorch revisión 6cb593b88cb0c411690b4957850058329526d87b.
git clone [email protected]:pytorch/pytorch.git
git checkout 6cb593b88cb0c411690b4957850058329526d87b
git submodule update --init —recursive
export CMAKE_PREFIX_PATH=${CONDA_PREFIX:-"$(dirname $(which conda))/../“}
MACOSX_DEPLOYMENT_TARGET=10.13 CC=clang CXX=clang++ python setup.py develop
python
>>> import torch
python setup.py install
python setup.py build
python setup.py test
# ERROR: test (unittest.loader._FailedTest)
# ERROR: test_scalar_binary_op (tests.test_tensor.TestComplexTensor)
from torch_complex import torch
a = torch.ones(3, dtype=torch.complex128)
a*a
RuntimeError: promoteTypes with complex numbers is not handled yet; figure out what the correct rules should be
@ezyang , @Roger-luo:
Todo lo relacionado con la promoción de tipos para las operaciones de tensor parece estar hecho en c10/core/ScalarType.h
He encontrado el error AT_ERROR("promoteTypes with complex numbers is not handled yet; figure out what the correct rules should be”);
Parece que tengo que agregar una entrada para c8 y c16 dentro de esta tabla.
¿Tiene esto algo que ver con 9515 ? Creo que esto es solo para llamar a funciones numpy.
¿Es ese un buen lugar para empezar?
9515 no está relacionado. Sin embargo, corregir esta ruta de código en ScalarType.h es un buen lugar para comenzar.
Arreglé la ruta de código en ScalarType.h
BinaryOps (add, sub, mul, div) funciona, pero solo si ambos argumentos son tensores.
Algunos otros problemas extraños, pero necesito mirarlo un poco más.
@dylanbespalko He agregado promociones de tipo aquí: https://github.com/pytorch/pytorch/pull/11641
Podría simplemente copiar eso, pero el problema es que esto rompe CUDA de alguna manera.
IIRC, hubo un error de conexión debido a la versión gcc. Tuve algunas soluciones allí.
Ah, gracias @Roger-luo. Estaba mirando los comentarios de #11641 . Haré un mejor trabajo copiando el código mañana.
¿Cómo puedo saber cuándo he roto CUDA cuando no tengo un dispositivo CUDA? ¿Supongo que el CI me lo dirá?
Sí, siempre que envíe un PR, le dirá cuál está roto. Y si todo pasa, entonces podríamos fusionarlo y hacer que todo funcione.
Ok, entonces comenzaré a enviar relaciones públicas para saber cuándo sucederá.
@dylanbespalko Hola, ¿todavía parece haber algunos errores en su entorno?
Si lo solucionas, por favor compártelo con nosotros. Muchas gracias.
Hola chicos,
Intenté hacer varias relaciones públicas después de copiar varias confirmaciones de @Roger-luo. Desafortunadamente, no tengo una GPU CUDA en este momento y las máquinas CI con CUDA no se están inicializando. No puedo recrear la falla de la prueba CUDA en este momento, así que volveré a esto en unas semanas cuando pueda ejecutar localmente en esa GPU. Parece prometedor, al menos.
@ezyang , @Roger-luo
He echado un vistazo al PR # 11641 de Roger:
También he echado un vistazo a algunos de los desarrollos recientes de PyTorch:
Me parece que se está desarrollando una nueva capacidad de extensión "fuera del árbol", que me permitiría investigar el soporte de números complejos sin romper el resto de pytorch. Mi objetivo es:
@ezyang
¿Puede proporcionar una línea de tiempo esperada para esta extensión de dispositivo/diseño/tipo de punto fuera del árbol que presentó? ¿Podemos esperar esta característica en los próximos 3 meses?
@ezyang
¿Puede fusionar la compatibilidad con números complejos en la CPU sin la compatibilidad con AVX/SSE? Planeo enviar lo siguiente en solicitudes de combinación separadas:
Planeo tener esto probado a través de intel/arm cpus en los próximos días.
@ezyang ,
Estoy investigando operaciones como fft()
y var()
donde la implementación del número complejo debe convertir los datos del tensor en un tensor doble de forma: (complex_shape, 2)
. Esto no funciona con ningún método de tensor existente:
Obviamente puedo hacer algo ineficiente como:
def to_float(tensor):
return th.stack((tensor.real().type(th.float64), tensor.imag().type(th.float64)), -1)
def to_complex(tensor):
tensor = tensor.type(th.complex128)
return tensor[..., 0] + 1j*tensor[..., 1]
Obviamente, eso es crear copias, cuando todo lo que necesito es static_cast<double>
y cambiar la forma del tensor a (old_shape, 2)
. ¿Tiene alguna sugerencia sobre cómo hacer esto?
Además, hay un truco en numpy que te permite hacer esto:
a = np.array([1 + 1j], dtype=np.complex128)
a.dtype = np.float64 ## This works
a = torch.tensor([1 + 1j], dtype=torch.complex128)
a.dtype = torch.float64 ## This does not work
La capacidad de establecer dtype realmente funciona en esta situación, sin embargo, podría ser impredecible.
Alguna información adicional sobre la interpretación de un número complejo como una matriz de números reales de longitud 2. Lo siguiente es válido en C++11.
Para cualquier puntero a un elemento de una matriz de números complejos p y cualquier índice de matriz válido i, reinterpret_cast
(p)[2 i] es la parte real del número complejo p[i], y reinterpret_cast (pag)[2 i + 1] es la parte imaginaria del número complejo p[i]. (Desde C++11)
Creo que esto significa que es posible convertir un tensor_complejo en un tensor_real con forma (forma_compleja, 2) y luego realizar una operación sin llamar a real()
y imag()
que asignaron nueva memoria.
@dylanbespalko Tenía miedo cuando preguntabas sobre esto :) La garantía std::complex
significa que si tienes el puntero de datos std::complex<float>*
, puedes convertirlo de forma segura en float*
(masculle un alias estricto) y luego páselo a cualquier cosa que esté usando. Si solo necesita implementar fft/var donde puede pasar esta repetición de bajo nivel, será más fácil.
Sin embargo, si necesita volver a ver literalmente un tensor complejo como un tensor flotante, estamos en un aprieto, porque no hay precedentes para esto en PyTorch hoy. Storage dtype siempre ha estado de acuerdo con Tensor dtype. Entonces, si realiza un almacenamiento complejo, no hay forma de revisarlo como un almacenamiento flotante.
Un pensamiento que he tenido es que tal vez deberíamos relajar este invariante. La idea es:
Sin embargo, no estoy seguro de cuánto código tendríamos que cambiar para que esto suceda.
@ezyang ,
Sí, esto era inevitable...
Si solo necesita implementar fft/var donde puede pasar esta repetición de bajo nivel, será más fácil.
Sí, esto es posible en muchos casos. ¿Puede proporcionar un fragmento de código de cómo interpretar los datos del tensor como un std::vector?
Sin embargo, si necesita volver a ver literalmente un tensor complejo como un tensor flotante,...
Me imagino que es raro ver un tensor usando otro dtype. Implementé un método set_dtype()
para Tensor
, pero recibí algunos errores. Tampoco actualicé los pasos para reflejar los cambios de forma. No estoy seguro de por qué la configuración de dtype funciona de forma numérica (¿es una coincidencia?), Sin embargo, cuando carga datos en un convertidor de digital a analógico (DAC), a menudo espera que los datos reales/imaginarios se intercalen. Quizás eso motivaría la necesidad de desacoplar el tipo de tensor del tipo de almacenamiento como ha sugerido.
Evitaré hacer esto por ahora. Estoy seguro de que hay otros cuellos de botella de rendimiento para mí.
Sí, esto es posible en muchos casos. ¿Puede proporcionar un fragmento de código de cómo interpretar los datos del tensor como un std::vector?
No es exactamente un std::vector, pero estoy imaginando algo como esto:
Tensor complex_tensor;
assert(complex_tensor.is_contiguous());
std::complex<float>* cp = complex_tensor.data_ptr<std::complex<float>>();
float* fp = reinterpret_cast<float*>(cp);
auto num_floats = complex_tensor.numel() * 2;
Implementé un método set_dtype() para Tensor, pero recibí algunos errores. Tampoco actualicé los pasos para reflejar los cambios de forma.
Sí, probablemente sea una mala idea si no arreglas los pasos. Además, no soy un gran fanático de los tensores que se transmutan en otros tipos de d; mejor hacerlo todo fuera de lugar :)
sin embargo, cuando carga datos en un convertidor de digital a analógico (DAC), a menudo espera que los datos reales/imaginarios se intercalen. Quizás eso motivaría la necesidad de desacoplar el tipo de tensor del tipo de almacenamiento como ha sugerido.
Sí, en última instancia, esto es lo correcto, pero estoy de acuerdo en que es más fácil no hacerlo ahora.
@ezyang ,
Estoy empezando a perder el tiempo con el soporte CUDA de números complejos.
Hay dos opciones binarias compatibles:
std::complex
que admite la asignación de memoria de host y dispositivo.El contenedor push::complex parece ser el camino a seguir. La API de Thrust::Complex sugiere que los contenedores thrust::complex<T>
se pueden asignar en la memoria del host y del dispositivo, mientras que los std::complex<T>
solo se pueden asignar en la memoria del host:
__host__ __device__ thrust::complex< T >::complex (const complex< T > &z) //thrust container
__host__ thrust::complex< T >::complex (const std::complex< T > &z) //stl container.
¿Esto sugiere que AT_DISPATCH_COMPLEX_TYPES debería establecer using scalar_t = thrust::complex<double>
en lugar de using scalar_t = std::complex<double>
?
¿Cómo llama Pytorch automáticamente a los equivalentes de CUDA de std::log
para tipos de datos reales? ¿Cómo sé que hay un equivalente CUDA de un núcleo matemático?
thrust::complex<double>
universalmente para CPU y CUDA es que en realidad no construimos contra empuje si haces una compilación solo de CPU. Supongo que hay un montón de opciones; podríamos lanzar nuestro propio tipo complejo (similar a cómo lanzamos nuestro propio medio tipo), o simplemente reinterpretar el lanzamiento para llegar a la victoria, porque std::complex<>
está definido para tener un diseño binario específico. Depende de usted, pero solo reinterpretar el lanzamiento entre los tipos parece más fácil por ahora.@iotamudelta ha planteado un problema con el cumplimiento de C++11 en #29547
std::real es solo constexpr de C++14
Si entiendo correctamente std::real()
debe ser constexpr
para que el compilador hcc pueda compilar la instrucción para __device__
.
Soluciones posibles:
complex<double>
a double
:abs
tampoco funciona: plantillaEncuentre una manera de envolver la función:
La mayoría de las llamadas a std::real se realizan en aten/src/ATen/native/cpu/zmath.h
. Ejemplo: reemplace inline
con constexpr
:
inline VALUE_TYPE real_impl (SCALAR_TYPE z)
->
constexpr VALUE_TYPE real_impl (SCALAR_TYPE z)
inline std::complex<float> real_impl <std::complex<float>> (std::complex<float> z)
-> constexpr std::complex<float> real_impl <std::complex<float>> (std::complex<float> z)
inline std::complex<float> real_impl <std::complex<double>> (std::complex<float> z)
-> constexpr std::complex<float> real_impl <std::complex<double>> (std::complex<float> z)
Esto no se compilará porque todavía hay una llamada anidada a std::real()
que no es un constexpr
.
3. Si uso std::complex
std::complex<double>
a double
que cumpla con sus requisitos?@iotamudelta , @bddppq , @ezyang ,
He agregado soporte para UnaryOps y BinaryOps complejas en CUDA push::complex API, pero necesito hacer algunas preguntas antes de enviarlo.
Definí una función de plantilla que le permite usar tipos de datos de empuje::complejos cuando se trata de números complejos.
aten/src/ATen/native/cuda/zmath.cuh
#pragma once
#include <complex>
#include <thrust/complex.h>
namespace at { namespace native {
namespace {
template <typename TYPE>
struct ztype_cuda {
using value_t = TYPE; // Complex template type
using thrust_t = TYPE; // Equivalent thrust type
};
template <>
struct ztype_cuda<std::complex<float>> {
using value_t = float;
using thrust_t = thrust::complex<float>;
};
template <>
struct ztype_cuda<std::complex<double>> {
using value_t = double;
using thrust_t = thrust::complex<double>;
};
} // end namespace
}} //end at::native
Luego en aten/src/ATen/native/cuda/BinaryOpsKernel.cu
Reemplazar:
void add_kernel_cuda(TensorIterator& iter, Scalar alpha_scalar) {
AT_DISPATCH_ALL_TYPES_AND2(kHalf, kBool, iter.common_dtype(), "add_cuda/sub_cuda", [&]() {
auto alpha = alpha_scalar.to<scalar_t>();
gpu_kernel_with_scalars(iter, [alpha]GPU_LAMBDA(scalar_t a, scalar_t b) -> scalar_t {
return a + alpha * b;
});
});
}
Con:
void add_kernel_cuda(TensorIterator& iter, Scalar alpha_scalar) {
AT_DISPATCH_ALL_TYPES_AND_COMPLEX_AND2(kHalf, kBool, iter.dtype(), "add_cuda/sub_cuda", [&]() {
using thrust_t = typename ztype_cuda<scalar_t>::thrust_t;
auto alpha = thrust_t(alpha_scalar.to<scalar_t>());
gpu_kernel_with_scalars(iter, [alpha]GPU_LAMBDA(thrust_t a, thrust_t b) -> thrust_t {
return a + alpha * b;
});
});
}
thrust_t
con algo más amigable para los números no complejos, como scalar_t_c
?cuComplex
en lugar de thrust::complex
?hip_complex
en su lugar?cuComplex
.Por favor déjame saber lo que piensa.
@iotamudelta
He actualizado la discusión sobre std::real(). ¿Puedes confirmar que std::complex
Hola @dylanbespalko ,
Supongo que de lo que se queja @iotamudelta es que al cast_and_store
para tipos complejos le falta un C10_HOST_DEVICE
, esto sería un UB si esa ruta de código se ejecuta alguna vez en la GPU.
Actualmente, esta utilidad de conversión dinámica solo se usa en GPU TensorIterator, y solo se usa cuando hay promoción de tipo. Debido a que el complejo no era compatible con la GPU actualmente, cast_and_store
para tipos complejos en este momento no tiene el calificador C10_HOST_DEVICE
y usa std::real
que está totalmente bien para un host. única función. No hay UB aquí porque no se usa y no hay nada de lo que deba preocuparse.
Pero dado que desea agregar soporte de complejo a GPU, y complejo es compatible con la promoción de tipos, como podemos ver en https://github.com/pytorch/pytorch/blob/master/c10/core/ScalarType.h#L398 - L420, debe tener mucho cuidado con esta ruta de código y es posible que deba hacer algunas modificaciones para que funcione:
Por supuesto, debe agregar C10_HOST_DEVICE
como lo está haciendo @iotamudelta en https://github.com/pytorch/pytorch/pull/29547 , pero eso no es suficiente, porque simplemente agregue C10_HOST_DEVICE
sin otros cambios sigue siendo UB en C++ 11 como lo menciona @iotamudelta , una buena solución podría ser lo que ha mencionado: use std::complex::real()
para reemplazar el std::real
.
Pero más allá de eso, si observa el archivo https://github.com/pytorch/pytorch/blob/master/c10/util/TypeCast.h , verá dentro fetch_and_cast
, hay algo como:
#ifndef C10_HOST_DEVICE
AT_FORALL_COMPLEX_TYPES(FETCH_AND_CAST_COMPLEX_CASE)
#endif
Esta ruta de código está deshabilitada en GPU. Necesitas habilitarlo y hacer que funcione.
Además, no vi ninguna conversión entre complex<float>
y complex<double>
dentro fetch_and_cast
y cast_and_store
. Es posible que también deba agregar la conversión para eso. Asegúrese de probar exhaustivamente la cobertura de estas funciones de todos los tipos de d.
CC: @ezyang y @bddppq
También @dylanbespalko , envíeme un mensaje de correo electrónico si está realizando algún cambio en TypeCast.h
en su PR.
Bien, tengo un par de cosas pequeñas que arreglar con torch.real()
y torch.imag()
en ARM, así que arreglaré TypeCast.h
y algunos otros mientras estoy en eso. Voy a cc ustedes en el PR.
Drive by comment: @smessmer nos está moviendo a C++ 14, momento en el cual no será UB. Dado que esto llegará pronto, si la UB no está causando problemas reales, no me preocuparía demasiado por eso.
@ezyang : Es bueno saberlo. La mayoría de las cosas de terceros como Eigen todavía llaman a std::real()
muy generosamente.
Para números no complejos, scalar_t y thrust_t son del mismo tipo. ¿Tal vez podría reemplazar el nombre de la variable push_t con algo más amigable con los números no complejos, como escalar_t_c?
No estoy muy seguro, pero scalar_t_c
parece un poco menos claro que thrust_t
(¿qué significa c
todos modos?) Los tipos en cuestión aquí parecen bastante específicos, por lo que parece mejor utilizar un nombre que hable directamente de la intención.
Ok, me quedaré con thrust_t
. Si alguien se sumerge en ztype_cuda<>()
, debería darse cuenta instantáneamente de que scalar_t
es thrust_t
para tipos no complejos.
¡Hola a todos! ¡Parece que se está haciendo un buen progreso para agregar soporte complejo a pytorch! ¡Gracias @dylanbespalko por tomar la iniciativa en esto y agregar soporte CUDA también! Desde un alto nivel, me interesa saber cuál es el progreso actual en el soporte complejo. Estoy principalmente interesado en una línea de tiempo aproximada para tener soporte CUDA para agregar y multiplicar tensores complejos (operaciones binarias). ¡Gracias!
Hola @sunilkpai ,
Tengo un PR abierto que debería admitir operaciones binarias y unarias en CUDA: #30295.
Un problema más es con la propagación hacia atrás. Creo que la derivada del complejo abs()
se define de manera diferente a los números reales. No estoy seguro de qué hacer al respecto, pero los derivados se definen en tools/autograd/derivatives.yaml
Creo que para números complejos /dz abs(z) = z/abs(z)
. Esto también se puede usar para números reales, pero probablemente será más lento que sgn(z)
@dylanbespalko Tal vez las tablas 4.1, 4.2 y 4.3 en mi Informe https://arxiv.org/pdf/1701.00392.pdf puedan ayudarlo a definir las derivadas.
Para las derivadas complejas (cálculo de Wirtinger), hay dos opciones.
Cálculo de la derivada con z o z conjugada.
Personalmente, me gusta más el derivado wrt z conjugado.
Se siente más natural para las operaciones de matriz y la actualización de gradiente no necesita un conjugado.
La definición de ellos es:
z
por z = x + jy
: dJ/dz = dJ/dx -j dJ/dy
z.conj
por z = x + jy
: dJ/dz.conj = dJ/dx + j dJ/dy
De su comentario, mi suposición es que usted calcula la derivada wrt z
en este momento.
En este caso la derivada es d abs(z) / d z = z.conj / abs(z)
. Cuando toma la otra definición, puede seguir la sugerencia de @Randl .
Déjame saber si debo explicar más. También tengo algunas implementaciones numpy para los derivados complejos.
Otra operación que sería útil (especialmente para proyectos en el espacio de la física que requieren compatibilidad con números complejos) es un controlador para el operador exp()
. En tensorflow, tenemos tf.exp(x + iy) = tf.exp(x) * (tf.cos(y) + 1j * tf.sin(y))
. ¿Es esto sencillo de implementar también en pytorch?
@sunilkpai , @boeddeker , @Randl ,
Gracias por el informe sobre los derivados complejos. Intentaré seguir eso y volveré sobre esto la próxima semana. Pensé en agregar algunos enlaces aquí y describir el estado del proyecto.
El estado de los números complejos no es oficial y debe agregarse a través de la extensión PyTorch:
Cada extensión contiene dos cosas:
.cpp
que contiene los registros del kernel matemático necesarios.test/
que contiene versiones muy simplificadas de los scripts de prueba de pytorch.¿Por qué no puedo imprimir un tensor complejo en la consola?
tensor.py
para omitir el formato de impresión.Estado actual del proyecto:
</li>
<li>Complex number specific code is under 'aten/src/ATen/native/cpu/zmath.h
</li>
<li>Complex number specific code is under 'aten/src/ATen/native/cuda/zmath.cuh
thrust::complex<T>
e incluyen los núcleos optimizados.El desarrollo actual:
--
para tu información Con respecto a los derivados complejos, tuvimos una larga discusión en Julia y su implementación ahora está en ChainRules (ver también: http://www.juliadiff.org/ChainRules.jl/dev/api.html#ChainRulesCore.Wirtinger) y Zygote ahora . En general, las personas solo necesitan
\partial L/\partial adjoint(z)
como el gradiente (por definición, es la dirección de disminución más rápida), pero la derivada es diferente a \partial L/\partial z
, se debe agregar una interfaz adicional, si queremos un soporte completo para el número complejo AD . Para conocer las reglas detalladas, puede verificar qué se implementa en ChainRules
o Zygote/lib
(dado que solo hay reglas genéricas, no hay reglas separadas para números complejos para la mayoría de los operadores, pase hacia atrás para cosas como matmul
están escritos en una definición genérica, por ejemplo adjoint(A) * B
)
¿Por qué no puedo imprimir un tensor complejo en la consola?
El objeto Tensor python tiene un formato de impresión bonito que llama a algunas funciones que no son compatibles.
Puede modificar el contenido de tensor.py para omitir el formato de impresión.
O simplemente puede convertir los tensores Pytorch en matrices Numpy y luego imprimir.
Creo que arreglé al menos parte de la impresión en https://github.com/Roger-luo/pytorch-complex para la depuración, etc. en primer lugar, no estoy seguro de si esto ayudaría ya que el maestro ha cambiado mucho en el pasado año. Puedes tomarlo si es útil, no voy a trabajar más en esto.
@dylanbespalko Soy relativamente inexperto con las partes internas de pytorch, ¡aunque he comenzado a aprender! Posiblemente podría intentar este cambio, aunque según lo que veo en aten/src/ATen/cpu/vec256/*
, no estoy seguro de si es necesario dado que el comportamiento predeterminado de std::exp(std::complex) es exactamente lo que mencioné. en mi comentario anterior: vea las notas de https://en.cppreference.com/w/cpp/numeric/complex/exp . Tampoco estoy seguro de cómo se traduce esto en la implementación de estas operaciones en CUDA (que actualmente parece estar limitado a real, imag, conj y angle).
@sunilkpai ,
He agregado el soporte AVX para exp()
usando la ecuación provista.
También noté que algunas cosas se rompieron debido a algunos cambios recientes en PyTorch. Los he arreglado en #30871.
@dylanbespalko
¿Existe un cronograma para la migración de TH a ATen?
¿Hay alguna manera en que pueda contribuir, dado que no estoy bien versado en el funcionamiento interno de pytorch?
Encontré una fórmula para la retropropagación del complejo svd en el arxiv y podría implementarla, si me muestran dónde
¡Gracias por tu trabajo!
@Jakob-Unfried
https://github.com/pytorch/pytorch/wiki/TH-to-ATen-porting-guide
Los núcleos TH se implementan en C y hay poco interés en agregar soporte complejo allí debido a todos los problemas inherentes de conteo de referencias. Puede seguir el progreso en aten/src/ATen/native/native_functions.yaml
donde se registra cada kernel:
Busque legacy::cpu::_th
y divida ese número por 3 para obtener el número de núcleos TH antiguos.
Busque legacy::cpu::_thnn
y divida ese número por 3 para obtener la cantidad de núcleos de red neuronal TH antiguos.
Cada núcleo se registra típicamente de 3 maneras diferentes:
1. Núcleo regular y = agregar (a, b)
2. Kernel en el lugar a = add_(a, b)
3. Núcleo de salida add_out(a, b, out=y)
La implementación real siempre está en el Kernel de salida y los otros 2 llaman a esa función.
Los núcleos nn tienden a ser más fáciles de portar porque tienen menos núcleos dependientes. Por lo tanto, si puede portar los núcleos en el orden inverso al que fueron implementados, entonces hará menos trabajo en general.
Comprobación del problema de seguimiento de la portabilidad https://github.com/pytorch/pytorch/issues/24507 , también cc @VitalyFedyunin
Aquí hay una actualización de estado sobre el soporte de números complejos según lo solicitado en #32437. Estoy de vuelta trabajando en el soporte relacionado con la CPU hoy.
angle()
, real()
, imag()
, conj()
.abs()
requerirá una implementación separada para números complejos. (ver notas de @boeddeker y @Randl arriba)El soporte de números complejos se implementa actualmente fuera del árbol. Esto es lo que eso significa:
Más actualizaciones por venir sobre este problema: https://github.com/pytorch/pytorch/issues/33152
Esto puede o no merecer un tema aparte, pero agradecería ver y pensar que actualmente es prácticamente más importante tener en la documentación algo que explique 'cómo funciona pytorch con números complejos en este momento'. también conocido como suma, multiplicación, algún tipo de norma, no puede tener pesos complejos, etc. todo lo cual se puede resumir en unas pocas líneas de documentación que explican cuál es el comportamiento actual previsto de alto nivel.
Esto puede o no merecer un tema aparte, pero agradecería ver y pensar que actualmente es prácticamente más importante tener en la documentación algo que explique 'cómo funciona pytorch con números complejos en este momento'. también conocido como suma, multiplicación, algún tipo de norma, no puede tener pesos complejos, etc. todo lo cual se puede resumir en unas pocas líneas de documentación que explican cuál es el comportamiento actual previsto de alto nivel.
Hola @redwrasse gracias por los comentarios! actualmente tenemos una nota para números complejos que habla sobre algunos fundamentos de antorcha y funciones complejas admitidas para tensores complejos en maestro
(la mayoría de los cuales están incluidos en la versión 1.6) https://pytorch.org/docs/master/complex_numbers.html?highlight=complex. ¿Puedes compartir qué otras funciones te interesan? feliz de hablar más sobre nuestro soporte actual y cuál es el plan para los próximos lanzamientos.
Esto puede o no merecer un tema aparte, pero agradecería ver y pensar que actualmente es prácticamente más importante tener en la documentación algo que explique 'cómo funciona pytorch con números complejos en este momento'. también conocido como suma, multiplicación, algún tipo de norma, no puede tener pesos complejos, etc. todo lo cual se puede resumir en unas pocas líneas de documentación que explican cuál es el comportamiento actual previsto de alto nivel.
Hola @redwrasse gracias por los comentarios! actualmente tenemos una nota para números complejos que habla sobre algunos fundamentos de antorcha y funciones complejas admitidas para tensores complejos en maestro
(la mayoría de los cuales están incluidos en la versión 1.6) https://pytorch.org/docs/master/complex_numbers.html?highlight=complex. ¿Puedes compartir qué otras funciones te interesan? feliz de hablar más sobre nuestro soporte actual y cuál es el plan para los próximos lanzamientos.
Gracias @anjali411 , es genial ver esta documentación, no la conocía anteriormente. Creo que lo que se necesita es al frente y al centro unas pocas líneas 'estado actual de soporte para redes neuronales complejas', pero déjame repasarlo...
Las personas que estén interesadas en autogradación compleja, pueden estar interesados en https://github.com/pytorch/pytorch/issues/41857 que trata sobre qué convención seguirá PyTorch (JAX o TF).
Comentario más útil
@sunilkpai , @boeddeker , @Randl ,
Gracias por el informe sobre los derivados complejos. Intentaré seguir eso y volveré sobre esto la próxima semana. Pensé en agregar algunos enlaces aquí y describir el estado del proyecto.
El estado de los números complejos no es oficial y debe agregarse a través de la extensión PyTorch:
Cada extensión contiene dos cosas:
.cpp
que contiene los registros del kernel matemático necesarios.test/
que contiene versiones muy simplificadas de los scripts de prueba de pytorch.Busque en los scripts de prueba para ver qué kernels son compatibles (y por qué otros no lo son).
¿Por qué no puedo imprimir un tensor complejo en la consola?
tensor.py
para omitir el formato de impresión.Estado actual del proyecto:
</li> <li>Complex number specific code is under 'aten/src/ATen/native/cpu/zmath.h
</li> <li>Complex number specific code is under 'aten/src/ATen/native/cuda/zmath.cuh
thrust::complex<T>
e incluyen los núcleos optimizados.El desarrollo actual:
--