Pytorch: Integrieren komplexer Tensoren

Erstellt am 16. Feb. 2017  ·  128Kommentare  ·  Quelle: pytorch/pytorch

Neue Beschreibung von @ezyang :

Unter https://github.com/Roger-luo/pytorch-complex wird daran gearbeitet

Organisationsprinzipien

  • Die Unterstützung komplexer Tensoren ist für PyTorch wichtig, und wir akzeptieren Patches für den Kern, die kleine Mengen an Code hinzufügen, um das Hinzufügen komplexer Unterstützung zu ermöglichen.
  • Das Hinzufügen von Komplexen beinhaltet das Schreiben vieler neuer Kernel und Codes: Wir möchten, dass dieser Code zunächst außerhalb des Repos lebt, sodass es für die Benutzer einfacher ist, schnell darauf zu iterieren, ohne den Hauptcodeüberprüfungsprozess von PyTorch durchlaufen zu müssen. Wir werden uns kurzfristig NICHT dazu verpflichten, große neue Kernel zu überprüfen, aber schließlich möchten wir, dass alle Kernel zu PyTorch zurückkehren.
  • Die externe Bibliothek kann separat von PyTorch erstellt werden, sodass Sie sie als separates Repository verwalten können, ohne mit PyTorch zusammenführen zu müssen (und mit vielen Zusammenführungskonflikten umgehen zu müssen).

    • PyTorch kann gelegentlich wichtige Änderungen in der C++-API vornehmen; Wenn Sie uns darauf aufmerksam machen, werden wir unser Möglichstes tun, um zur Lösung dieser Probleme beizutragen.

  • Die dafür benötigten Hooks werden NICHT mit PyTorch 1.0 ausgeliefert, aber sie werden in nicht allzu ferner Zukunft mit einer veröffentlichten Version von PyTorch ausgeliefert.

Wie arbeite ich an komplexen Kerneln?

So sieht der Workflow im stationären Zustand aus.

PyTorch enthält nativ APIs zum Verweisen auf den komplexen dtype, aber sie tun standardmäßig nichts. PyTorch definiert Torch.complex64 und Torch.complex128, die sich auf komplexe Tensoren beziehen. Wenn Sie jedoch versuchen, einen Tensor auf diese Weise zu konstruieren, gibt PyTorch standardmäßig einen Fehler aus:

>>> torch.zeros({2,2}, dtype=torch.complex64)
RuntimeError: complex64 not supported by PyTorch

@ezyang hat einen Patch bereitgestellt, der diese dtypes zu PyTorch hinzufügt. https://github.com/pytorch/pytorch/pull/11173

Mittelfristig werden wir die Unterstützung für grundlegende Funktionen (wie das Zuweisen eines Tensors von Nullen) zusammenführen, damit sie von PyTorch nativ unterstützt werden. Ein vernünftiger Anhaltspunkt dafür, was Unterstützung „einfach“ ist, ist die native Unterstützung von PyTorch für CPU-Halbtensoren (die extrem verarmt sind).

PyTorch veröffentlicht eine Schnittstelle zum Registrieren einer Implementierung komplexer Tensoren. Die Implementierung erbt von der TypeDefault-Klasse (https://github.com/pytorch/pytorch/pull/11013) und überschreibt Methoden dieser Klasse, um Implementierungen von Funktionen zu definieren, für die wir komplexe Implementierungen haben. Es wird in etwa so aussehen:

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
  }
  // ...
}

Diese Klasse überschreibt genau die Typen, die für complex unterstützt werden; Alle anderen Implementierungen werden von TypeDefault bereitgestellt und führen standardmäßig zu Fehlern.

Es wird eine kanonische Liste von Methoden geben, die von Type (der gesamten Schnittstelle) als automatisch generierte Datei unterstützt werden, die in das PyTorch-Quellrepository eingecheckt wird; Wir werden API-Änderungen durch Diffs an diese Datei übermitteln. Im Allgemeinen stehen die Methoden in Eins-zu-Eins-Entsprechung mit ihren entsprechenden Namen im PyTorch-Frontend.

Wenn Sie eine Operation verwenden, die Sie noch nicht implementiert haben,

WARNUNG: Wir beabsichtigen, Type in ein neues System umzugestalten, das auch die offene Registrierung neuer Operationen unterstützt (dies funktioniert offensichtlich nicht, wenn Sie eine einzelne Oberklasse haben, die alle Methoden definiert, die Sie möglicherweise unterstützen möchten). Versuchen Sie daher, sich nicht zu sehr an die spezielle Implementierungsstrategie zu binden, Type als Unterklasse zu schreiben.

Um neue, ausschließlich komplexe Vorgänge zu veröffentlichen, verwenden Sie die C++-Erweiterungs-API. Die C++-Erweiterungs-API ist unter https://pytorch.org/tutorials/advanced/cpp_extension.html dokumentiert. Im Wesentlichen können Sie eine C++-Funktion wie folgt schreiben:

at::Tensor imag(at::Tensor z) {
  ...
}

Und dann generiert die C++-Erweiterungs-API eine Python-Bindung, sodass Sie diese Funktion von Python aus aufrufen.

Einige Operationen lassen sich „einfach“ in PyTorch, wie es heute existiert, integrieren. Zum Beispiel ist es für die Implementierung von Binäroperationen wahrscheinlich sinnvoller, add_kernel in BinaryOpsKernel.cpp so zu erweitern, dass es über komplexe Typen verteilt (und Sie es dann kostenlos bekommen, weil std::complex Addition implementiert). Solange diese Patches klein und eigenständig sind, versprechen wir, sie zeitnah zusammenzuführen.

Es sollte IMMER möglich sein, die Blockierung aufzuheben, indem Sie einfach eine Überschreibung für Type schreiben, anstatt die vorhandene Infrastruktur zu verwenden, und liberales Kopieren und Einfügen durchführen. Aber vermeiden wir es, wenn es einfach ist!

Autograd. Solange Sie an Operationen arbeiten, für die bereits Ableitungsformeln definiert sind, erhalten Sie „automatisch“ Autograd-Unterstützung, solange Sie komplexe Unterstützung für alle konstituierenden Funktionen implementieren, die in der Rückwärtsimplementierung von derivative.yaml aufgerufen werden .

In einigen Fällen müssen wir möglicherweise Autograd-Formeln anpassen, damit sie für komplexe Zahlen funktionieren. zB ist der Gradient von 'abs' nicht 'grad'. self.sign()'. In diesen Fällen müssen wir lediglich die Autograd-Formel von „abs“ in „abs_backward“ ändern, was eine Funktion ist, die überschrieben werden kann.

Für die allgemeine komplexe Rückwärtsausbreitung gibt es einige Referenzen:

  1. Akiras „Complex Valued Neural Networks“.
  2. https://giggleliu.github.io/2018/02/01/complex_bp.html

Im Allgemeinen müssen wir den Autograd nicht ändern, da wir in den meisten Fällen nur die Ableitungen einer reellwertigen Funktion (den Verlust) berechnen.

Arbeitsplan

Viele der notwendigen Teile sind heute vorhanden, aber sie sind nicht vollständig zusammengesetzt. Hier ist, was getan werden muss.

  • [X] Codemod TH zu nicht ifdef echt https://github.com/pytorch/pytorch/pull/11163
  • [X] Eingebaute Unterstützung für Torch.complex64- und Torch.complex128-Dtypes. https://github.com/pytorch/pytorch/pull/11173
  • [X] Eine Schnittstelle zum Registrieren von CPUComplexType usw., sodass diese Implementierung aufgerufen wird, wenn Sie einen komplexen Tensor mit dtype=torch.complex64 anfordern oder eine Operation mit komplexen Tensoren ausführen.
  • [X] Lande https://github.com/pytorch/pytorch/pull/11013
  • [X] Ein End-to-End-Beispiel, einschließlich eines funktionierenden Build-Systems, eines separat kompilierbaren C++-Programms, das mit libtorch verknüpft ist und die oben erwähnte Schnittstelle verwendet, um eine komplexe Tensorzuweisung zu implementieren.

Kurzfristiger Integrationsplan. Diese Operationen sind „einfach“ zu implementieren, und daher sollten wir sie so schnell wie möglich in PyTorch integrieren.

  • [X] Grundlegende Tensorfabriken: Torch.leer, Torch.Nullen, Torch.Eins
  • [ ] CPU-Binäroperationen: add, sub, mul, div #11641
  • [ ] FFT
  • [ ] ???

Kernel-Implementierung:

TODO: Erstellen Sie eine Liste basierend auf https://github.com/Roger-luo/TH/blob/master/ChangeLog.md

Andere komplexe verwandte Aufgaben:

  • [ ] Finden Sie die Type-Promotion-Regeln für komplexe Tensoren heraus und implementieren Sie sie in promoteTypes #11641

Inhalt der historischen Ausgabe

Ursprünglicher Kommentar von @PhilippPelz

Ich habe mich gefragt, ob Interesse daran besteht, komplexe Tensoren in Pytorch zu integrieren.
Für CPU-Unterstützung gibt es ztorch und ich habe vor einiger Zeit z-cutorch ( https://github.com/PhilippPelz/z-cutorch ) geschrieben. Es ist ein Fork-Off-Cutorch vor dem Refactoring für CudaHalfTensor (habe die Hardware noch nicht).
Wenn es nicht zu viel Arbeit ist, würde ich es gerne langsam mit Pytorch integrieren. Ich verwende matplotlib zum Plotten über fb.ptyhon und es stellt sich jedes Mal als großer Schmerz heraus, wenn ich mein System neu installiere (alle Abhängigkeiten kompiliere), außerdem scheint Pytorch bald unter Windows zu funktionieren, auf dem einer meiner Experiment-PCs läuft.
Ich bräuchte auch komplexe Farbverläufe, also würde ich früher oder später auch auf Autograd tippen.
Während tf komplexe Tensoren per se unterstützt, scheinen viele Operationen es noch nicht zu unterstützen (https://github.com/tensorflow/tensorflow/issues/2255), außerdem scheint es für meine Zwecke ein bisschen schwergewichtig zu sein.

Vielleicht könnte jemand ein paar Worte sagen, wie und wo man damit anfangen soll, wenn es eine willkommene Idee ist.

feature complex triaged

Hilfreichster Kommentar

@sunilkpai , @boeddeker , @Randl ,

Danke für den Bericht über die komplexen Derivate. Ich werde versuchen, dem zu folgen, und ich werde nächste Woche darauf zurückkommen. Ich dachte, ich würde hier einige Links hinzufügen und den Projektstatus beschreiben.

Der Status komplexer Zahlen wird inoffiziell unterstützt und muss über die PyTorch-Erweiterung hinzugefügt werden:

Jede Erweiterung enthält zwei Dinge:

  • Ein .cpp , das alle notwendigen mathematischen Kernel-Registrierungen enthält.
  • Ein test/ -Ordner, der sehr vereinfachte Versionen der Pytorch-Testskripte enthält.
    Sehen Sie in den Testskripten nach, welche Kernel unterstützt werden (und warum andere nicht).

Warum kann ich einen komplexen Tensor nicht auf der Konsole ausgeben?

  • Das Tensor-Python-Objekt hat eine schön gedruckte Formatierung, die einige nicht unterstützte Funktionen aufruft.

    • Sie können den Inhalt von tensor.py ändern, um die Druckformatierung zu umgehen.

    • Oder Sie können Pytorch-Tensoren einfach in Numpy-Arrays konvertieren und dann drucken.

Aktueller Projektstatus:

  • Die CPU-Abdeckung ist ziemlich gut.

    • Die Kernel sind in PyTorch unter 'aten/src/ATen/native/cpu/ </li> <li>Complex number specific code is under 'aten/src/ATen/native/cpu/zmath.h implementiert

    • Die Intel AVX256-Beschleunigung befindet sich unter „aten/src/ATen/cpu/vec256/“.



      • @sunilkpai : Ich kannte die Optimierung von exp nicht. Dies ist der Ordner, in dem Sie das hinzufügen.


      • Lassen Sie mich wissen, ob Sie sich wohl fühlen, die Änderung vorzunehmen.



  • Die GPU-Abdeckung ist auf binäre und unäre Operationen beschränkt:

    • Die Kernel sind in PyTorch unter 'aten/src/ATen/native/cuda/* </li> <li>Complex number specific code is under 'aten/src/ATen/native/cuda/zmath.cuh implementiert

    • Es werden thrust::complex<T> -Datentypen verwendet, die die optimierten Kernel enthalten.

Aktuelle Entwicklung:

  • Warten auf C-basierte TH-Kernel, die in den C++-ATen-Ordner portiert werden.

    • Die Funktion rand() wird benötigt, um die Testfälle zu den internen Tests von Pytorch zu portieren.

    • Einige Indizierungsvorgänge werden derzeit nicht portiert.

    • Derzeit gibt es 168/1300 Mathematikkerne (gegenüber 230 im Oktober), die von TH auf ATen portiert werden müssen.

  • Ich werde versuchen, Unterstützung für komplexe Zahlen hinzuzufügen, sobald diese Kernel in ATen verfügbar sind.

--

Alle 128 Kommentare

Ich denke, wir wären daran interessiert, eine optionale Unterstützung für komplexe Tensoren hinzuzufügen. Der beste Weg wäre, die C-Bibliotheken in torch/lib zu forken und zu bearbeiten. Dies sollte mit dem Meister konfliktfrei sein, damit Sie dies lange tun können. Sobald Sie die Bibliotheken in einen verwendbaren Zustand gebracht haben, können Sie mit dem Schreiben der Bindungen beginnen, und hier können wir einige Hinweise geben, wie Sie zu diesem Zeitpunkt Konflikte vermeiden können.

Ich habe TH mit komplexen Typen kompiliert. Was muss ich für die Python-Integration hinzufügen?

@PhilippPelz meinst du so: https://github.com/facebook/ztorch/tree/master/lib/THZ ? oder haben Sie Ihren eigenen Fork von TH gebaut, der komplexe Typen ermöglicht?

@killeent hat einige Notizen darüber, wie TH an Python gebunden ist, er kann diese teilen.

Im Allgemeinen würde ich THZ vorziehen, um komplexe Tensoren zu erhalten, da es Tests usw.

Der Aufbau eines CUDA-Backends für komplexe Tensoren ist jedoch ein ziemlich großer Aufwand, damit haben wir noch nicht einmal begonnen.

Ich habe vor einiger Zeit z-cutorch ( https://github.com/PhilippPelz/z-cutorch ) geschrieben. Es ist ein Fork-Off-Cutorch vor dem Refactoring für CudaHalfTensor (habe die Hardware noch nicht).

Das ist toll. Ich schätze, du hast bereits große Anstrengungen in diese Richtung getrieben :)

@soumith Ich habe eine Gabelung von TH mit komplexen Typen gemacht. Im Grunde eine THGenerateComplexTypes.h + hinzugefügte BLAS + LAPACK-Routinen, der Rest war fast kostenlos. Es schien mir viel weniger Arbeit zu sein, als zu prüfen, welche Teile von THZ kompatibel sind, und dann das Einfügen zu kopieren.

Ich stecke gerade mit dem Kompilieren von THPP fest und finde Compiler-Meldungen wie

/home/philipp/projects/pytorch/torch/lib/tmp_install/include/TH/generic/THBlas.h:6:40: Fehler: erwartetes ',' oder '...' vor '*' Token
TH_API void THBlas_(swap)(long n, real *, long incx, real *, long incy);

ist etwas knifflig.

Ich würde mich über Hilfe bei der Aktivierung der Python-Integration freuen. Das CUDA-Backend sollte hauptsächlich aus z-cutorch kopiert und eingefügt werden.

@PhilippPelz hier sind einige Anmerkungen zu PyTorch Wraps TH: https://gist.github.com/killeent/4675635b40b61a45cac2f95a285ce3c0

@killeent danke, sieht sehr hilfreich aus. lib/build_all.sh wird jetzt kompiliert, ich glaube, ich kann mir das csrc-Verzeichnis ansehen.

Das läuft jetzt:

Fackel als th importieren
importiere numpy als np

a = np.array([1+1j,2+2j])
b = np.array([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()
print(ath.numpy())

Aus: [ 4.+4.j 6.+6.j]

zusammen mit den meisten mathematischen Funktionen.
Ich werde in den nächsten Wochen Komfortfunktionen und ffts hinzufügen. Ich denke, es müssen Tests für alles durchgeführt werden, bevor Sie dies zusammenführen können. Wenn Sie jemanden kennen, der sich für komplexe Tensoren interessiert und bereit wäre, zum Schreiben der Tests beizutragen, wäre das großartig. Dieses Papier kommt mir in den Sinn: Deep Complex Networks , vielleicht wären diese Leute interessiert.
Ich werde nicht die Zeit haben, alle Tests alleine zu schreiben.

@PhilippPelz Danke für deine Kommentare. Ich überprüfe Ihre Implementierung. Und erstens bin ich mir bei Ihrer ger -Implementierung nicht sicher. Einige komplexe Blas-Funktionen sind nicht in Ihrer THBlas.c enthalten, wie Sie GER als zger_ und cger_ in den Generate-Headern definiert haben, aber es gibt keine Blas-Funktion mit cger_ in der Datei generic/THBlas.c . Allerdings kann ich Ihr gemv und einige andere Funktionen verwenden. Und meiner Meinung nach sollten Sie .gch zu .gitignore hinzufügen? Haben Sie alle Ihre Erweiterungen zu Ihrer Gabel geschoben? Ich kann zunächst basierend auf Ihrer Implementierung eine Pull-Anforderung an Ihren Master stellen.

Und für DOT sind vielleicht für komplexe Vektoren dotc Routinen für Punkte häufiger?

Und ja, wenn die Verwendung real einfacher für die Implementierung wäre, fühlte ich mich nur seltsam, wenn real tatsächlich ein Komplex ist ...

Und für Tests habe ich keine früheren Tests für TH gesehen. Wo soll ich diese Tests schreiben? oder wir schreiben einfach ein paar Python-Tests

Ja, tut mir leid, ich sehe, ich habe möglicherweise nicht alles gepusht, was benötigt wird. Ich werde es am Montag nochmal prüfen. Einige Deklarationen fehlen, z. zger und cger

Für DOT verwende ich cdotc und zdotc, sie scheinen zu fehlen, ich werde nächste Woche aktualisieren.

Erkundigen Sie sich bei den Betreuern von pytorch, welche Benennung sie wirklich bevorzugen. Deine Version gefällt mir besser, habe mir nur noch nicht die Mühe gemacht.

Ja, Python-Tests für das mathematische Zeug. Sollte für die meisten Funktionen leicht geändert werden können, um auch komplexe Nummernprüfungen einzuschließen.

Cool, dass du dir das auch anschaust!

Ok, ich habe einige Änderungen vorgenommen. TH Blas-Routinen gibt es jetzt für Komplexe

@PhilippPelz Ich habe gerade eine Pull-Anfrage an Ihr Repo gestellt. Und für komplexe lineare Schichten und einige andere Operatoren. Es könnte viele hermitische Operationen geben (wie bp für komplexe lineare Schichten). Vielleicht eine Funktion für einen Tensor hinzufügen? Haben Sie den THNN-Teil überprüft?

Ja hermitian ist nützlich. cuda fft funktioniert jetzt. cpu fft könnte von numpy gewickelt werden. Ich habe THNN oder THCUNN noch nicht berührt.

@PhilippPelz Ich habe in der PR einen einfachen Einsiedler hinzugefügt. Und könnten Sie es überprüfen. So könnten wir sehen, ob diese Änderungen geeignet sind, und zum nächsten Schritt übergehen. Danke! PS. Es scheint, dass Sie einige Überschriften verpasst haben, ich korrigiere auch das und einige andere Warnungen. Sollten wir für eine komplexe Funktion mit reeller Ausgabe einen reellen Tensor anstelle eines komplexen Tensors zurückgeben? Ich habe Kopiermethoden zwischen komplexen und realen Typen implementiert, also ist es möglich.

Ich werde alle Commits nach Ihrer Überprüfung rebasen.

@PhilippPelz Hallo, ich bin ziemlich verwirrt über THPP Teil, den du implementiert hast. Warum ist es in Traits.hpp vom Schub abhängig?. Dies führt beim Kompilieren ohne cuda zu Fehlern. Kann man nur like verwendenoderin Traits.hpp ? Ich habe es nicht herausgefunden. Vielleicht könntest du ein paar Anhaltspunkte geben?

@Roger-luo Ja, damit habe ich auch woanders einige Probleme. Die von uns verwendeten komplexen Typen sollten entweder aus complex.h oder std::complex stammen. Da THPP der C++-Wrapper ist, ist vielleicht std::complex besser geeignet. Kannst du das bitte ändern?

Thrust verursacht aus genau demselben Grund auch Probleme beim Versuch, cffi-Erweiterungen zu erstellen. Im Moment mache ich eine Problemumgehung, aber der richtige Weg wäre, den Komplextyp in THC in cuFloatComplex/cuDoubleComplex zu ändern. damit sich der cffi-compiler nicht beschwert. Ich möchte jetzt nur mit der Recherche fortfahren, das nimmt mir viel zu viel Zeit :( . Wenn Sie Zeit haben, tun Sie es bitte.

Auch das Erstellen einer cffi-Erweiterung mit benutzerdefinierten Kernel-Aufrufen ist ziemlich umständlich, weil man immer eine extra Bibliothek erstellen muss, die mit nvcc kompiliert wird, die dann mit einem cffi-Wrapper verknüpft wird. Ich denke, es gibt keinen anderen Weg. Man könnte cffi im ABI-Modus verwenden, aber die Website sagt: „Der API-Modus kompiliert stattdessen einen CPython-C-Wrapper, der die Zielfunktion direkt aufruft. Er ist vergleichsweise massiv schneller (und funktioniert besser als libffi es jemals kann).“

@PhilippPelz könnte vielleicht reinterpret_cast eine Lösung sein? Ich denke, es sollte in cuComplex geändert werden und reinterpret_cast in THPP verwenden. Ich werde es erstmal versuchen...

Ja, ich denke, es gibt keinen anderen Weg als reinterpret_cast, wenn Sie möchten, dass THPP auch ohne installiertes cuda erstellt wird.

@PhilippPelz Ich möchte helfen. Gibt es irgendwo eine Todo-Liste?

THNN und THCUNN müssen für komplexe Typen aktiviert werden. Können Sie sich mit @roger-luo abstimmen? Wenn wir eine Integration mit Master anstreben, müssen außerdem Unit-Tests für alle komplexen Methoden geschrieben werden.

@elbamos Die meiste Arbeit in THNN wird sich auf die Implementierung neuer komplexer Backpropagtion-Methoden für jede vorhandene Schicht beziehen. In Philipps Fork steckt ein WIP PR. Ich habe einige Referenzen aufgelistet.

@apaszke @soumith @PhilippPelz Und da sind zwei Fragen:

  • Weiß jemand, warum es eine weitere GenerateXXXTypes.h -Datei in THS gibt? Ähnlich sieht es bei denen in TH aus.

  • Wofür ist der folgende Code in 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);
  }
}

Irgendwelche Vorschläge zur Implementierung der zugehörigen komplexen Version? Ich bin mir nicht sicher, ob die folgende Implementierung korrekt ist ...

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>);
  }
}

Vorheriges decodeUInt128XE wird als deklariert

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);
}

Ich verwende derzeit std::complex<T> anstelle von T _Complex in THPP . Ich bin mir nicht sicher, ob dies noch von Python verwendet werden kann. Oder nur der c-Typ T _Complex ist für Python verwendbar. Hier ist der Typ von dst also std::complex<T> .

Und wenn ich mit dieser Implementierung richtig liege, brauchen wir wahrscheinlich eine uint128_t -Implementierung, wie https://github.com/calccrypto/uint128_t ? Da anscheinend nicht alle Compiler 128-Bit-Integer unterstützen (gcc hat int128_t und uint128_t).

@PhilippPelz Mir ist aufgefallen, dass bei Ihrem Fork keine Probleme aktiviert sind. Wie ist der Status Ihres Projekts? Ich bin ein wenig enttäuscht, dass komplexe Tensoren nicht auf der Roadmap für Pytorch stehen

@el3ment Ich habe ein komplexes Backend für die CPU hinzugefügt https://github.com/pytorch/pytorch/pull/4899 Aber es ist noch nicht überprüft ... Und ich habe keine Kommentare für meine PR erhalten, also habe ich mich an die Verwendung gewandt die Programmiersprache Julia vor kurzem ...

Ich habe letztes Mal eine E-Mail an @PhilippPelz gesendet , ich schätze, sein Repo ist noch unter v0.1 und er ist bis September mit seiner Abschlussarbeit beschäftigt? Und ich habe zwar am neuen CUDA-Backend von v0.3 gearbeitet, aber ich habe keine Zeit, all diese Bindungen alleine fertigzustellen. Die Map/Reduce-Funktionen unterscheiden sich von v0.1 mit einigen Optimierungen, aber sie können nicht einfach konvertiert werden, um komplexe Zahlen zu unterstützen. Ich würde mich freuen, wenn jemand bereit ist zu helfen...

Ich bin bereit zu helfen.

Am 10. April 2018 um 22:52 Uhr schrieb Rogerluo [email protected] :

@el3ment Ich habe ein komplexes Backend für CPU #4899 hinzugefügt

Ich habe letztes Mal eine E-Mail an @PhilippPelz gesendet , ich schätze, sein Repo ist noch unter v0.1 und er ist bis September mit seiner Abschlussarbeit beschäftigt? Und ich habe zwar am neuen CUDA-Backend von v0.3 gearbeitet, aber ich habe keine Zeit, all diese Bindungen alleine fertigzustellen. Die Map/Reduce-Funktionen unterscheiden sich von v0.1 mit einigen Optimierungen, aber sie können nicht einfach konvertiert werden, um komplexe Zahlen zu unterstützen. Ich würde mich freuen, wenn jemand bereit ist zu helfen...


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

@elbamos cool, es scheint, dass das Pytorch-Team eine separate Implementierung bevorzugt. Ich werde meine Gabel später für die anderen Teile später aktualisieren. Aber ich habe wirklich keine Zeit dafür und ich denke, wir sollten mit der Arbeit daran beginnen, wenn es einen Plan vom Pytorch-Team gibt, weil dies eine große Erweiterung für Pytorch wäre.

Hallo, mein Code befindet sich auf einem Commit nach v0.2

Ich hatte gesehen, dass es einen ziemlich großen Refactor gab, der den gesamten Tensorcode nach Aten verschob. Das bedeutet, dass man meinen Fork nicht einfach in die aktuelle Version einbinden kann und möglicherweise mehr Arbeit erforderlich ist.

Ich schreibe immer noch an meiner Doktorarbeit, aber ich hatte sowieso vor, auf 0.4 zu warten, bis die Zusammenführung von Variable und Tensor veröffentlicht wird. Ich fürchte, es könnte zu viel Refactoring im Gange sein, um es einzuholen, wenn man es früher macht.

@elbamos Wenn Sie möchten, können Sie anfangen, Dinge zu meiner Gabel hinzuzufügen, ich werde sie zusammenführen. An Ihrer Stelle würde ich einfach implementieren, was Sie für jedes Projekt benötigen, das Sie durchführen. TH(CU)NN ist eine ziemlich große Schnittstelle und würde eine enorme Arbeitsbelastung bedeuten.

@el3ment Ich habe keine Zeit, an den Problemen anderer zu arbeiten. Ich werde jedoch Dinge zusammenführen, wenn Sie etwas implementieren müssen, das nicht vorhanden ist.

Wenn Sie nur etwas wollen, das sofort mit komplexen Zahlen funktioniert, würde ich Tensorflow wärmstens empfehlen.

Ich helfe auch, wenn es Kompilierungsprobleme gibt.

Wenn ich mit Postdoc weitermache, werde ich das ganze Zeug irgendwann auf die aktuelle Version portieren. Schade, dass Facebook das nicht unterstützen will. :((

@PhilippPelz Einverstanden, es ist wirklich traurig und tatsächlich unterstützt Tensorflow nicht alle Operatoren in der Quantenphysik ... Ich habe angefangen, Julia zu verwenden und Python aufzugeben.

@Roger-luo interessant, verwendest du ein bestimmtes Julia-Paket oder ist das alles selbstgeschriebener Code?

@PhilippPelz Ich entwickle in Julia (seit PyTorch PR) ein Quanten-Vielkörper-Toolkit, das eine komplexe/echte neuronale Netzwerkimplementierung enthält, die auf einigen früheren Artikeln über komplexe neuronale Netzwerke basiert, und ich fand, dass es so einfach ist, mit Julias zu entwickeln Metaprogrammierung. Ich habe es gerade in QMTK.jl eingefügt , es ist noch in Arbeit und ich habe noch nicht alles fertig, was ich will. PyTorch inspiriert mich zwar sehr, aber sorry für den komplexen Support...

Aber ich habe Pläne, es in Zukunft in ein einzelnes Paket für neuronale Netzwerke zu trennen (ich möchte im Moment nur nicht mehrere Repos verwalten). Und es werden noch mehr Leute aus dem Institut für Physik, CAS, in die Entwicklung einsteigen. Ich akzeptiere PRs nach der ersten getaggten Version (die in ein paar Wochen erscheinen wird).

Sie können es sich ansehen, wenn Sie an seiner Entwicklung interessiert sind.

Wenn das PyTorch-Team in Zukunft noch Pläne für komplexen Support hat, bin ich jedoch bereit zu helfen.

Cool, werde ich im Auge behalten!

Hey Leute, es tut uns leid, dass wir auf dieses Problem seit seiner Eröffnung nicht geantwortet haben.

Hier zwei Fakten:

  1. Wir stimmen absolut darin überein, dass PyTorch komplexe Unterstützung benötigt, und
  2. Wir haben nicht die Arbeitskraft, um den langen Schwanz, den alle komplexen Operationen benötigen würden, angemessen auszufüllen. (Als Beweis dafür schauen Sie sich die spärliche Unterstützung an, die im Master ist und hinkt.)

Seit der Eröffnung dieses Problems im Jahr 2017 haben sich einige wichtige Dinge geändert, die die Implementierung komplexer Unterstützung möglicherweise etwas einfacher machen. Das erste ist, dass wir jetzt ATen haben, eine ergonomische C++-Bibliothek zur Manipulation von Tensoren. Das bedeutet, dass Sie keine riesigen Schwaden von TH/THC-Code kopieren und einfügen müssen und hoffen, dass Sie das manuelle Refcounting richtig hinbekommen haben. Sie können C++-Code schreiben, als wäre es Python, und es wird schnell laufen. Zweitens arbeiten wir an einer neuen Version von ATen namens C10, die es viel ernster mit offenen Backends als ATen (was eine geschlossene Sache ist) ist, was es einfacher machen sollte, an komplexem Support zu arbeiten, da dies nicht der Fall wäre Es ist nicht erforderlich, PyTorch tatsächlich zu forken, sondern lediglich ein neues Codeverzeichnis hinzuzufügen.

Also, @Roger-luo und @PhilippPelz , wir würden gerne Ihre Hilfe dabei haben, das komplexe Backend Wirklichkeit werden zu lassen, aber wir würden wirklich gerne einen Weg finden, dies zu tun, der uns hilft, es in Zukunft nachhaltig zu pflegen. Lassen Sie uns wissen, was Sie denken.

@ezyang Wenn Ihnen die Arbeitskräfte fehlen, könnte ich versuchen, den komplexen Tensorteil in Zukunft aufrechtzuerhalten. Ich habe gerade mit meiner Promotion begonnen (und dies ist eigentlich mein Zwischenjahr), und daher werde ich nicht das Problem haben, meine Abschlussarbeit zu schreiben letzten Jahren zumindest. Aber ohne Feedback vom Pytorch-Team kann ich wirklich nicht weiter beitragen. Ich denke, es sollte eine Roadmap für diese große Erweiterung geben. Und wir könnten komplexe Unterstützung reibungslos hinzufügen, sodass Ihre Leute keine große PR überprüfen müssen, und es wird die Bemühungen der Entwickler beim Verfolgen des Master-Zweigs erleichtern.

Erstens denke ich, dass das Hauptproblem bei der komplexen Unterstützung der CUDA-Teil wäre. Es ist ziemlich einfach, den CPU-Teil mit ATen oder anderen Bibliotheken zu unterstützen. Ich kann den CPU-Teil in nur wenigen Tagen neu schreiben, wenn es Feedback gibt. Es gibt ein paar Probleme, die ich für den CUDA-Teil betreffen könnte, und ich denke, dies könnte zu zwei unterschiedlichen Ansätzen führen:

  1. Verwenden Sie float2 usw., um einen einzelnen komplexen Wert zu simulieren, wie es cuComplex im CUDA-Teil tut.
  2. Verwenden Sie die vorhandenen FloatTensor und DoubleTensor , um einen komplexen Tensor im C++-Teil von ATen zu simulieren.

Der Grund für den zweiten Ansatz liegt darin, dass Pytorch in THC einige Tricks verwendet, um Zuordnungs-/Reduzierungsvorgänge zu beschleunigen, und es trivialerweise nicht für cuComplex geeignet ist, da cuComplex tatsächlich float2 ist __shfl_xxx Funktionen unterstützen float2 nicht nativ. Ich bin mir im Moment nicht sicher, wie ich eine solche Funktion für float2 effizient simulieren kann.

Der zweite Ansatz wäre einfacher, weil wir uns jetzt nicht mehr um die Hardware kümmern müssen und unsere neue komplexe Erweiterungsarbeit auf alten Geräten viel einfacher machen können. Dies kann jedoch aufgrund der nicht zusammenhängenden Speicheradresse zu einem gewissen Overhead führen.

Außerdem habe ich festgestellt, dass wir, um komplexe Zahlen in ATen zu integrieren, möglicherweise vier verschiedene Typen handhaben müssen, die auf der Hardware tatsächlich gleich sind: std::complex , thrust::complex , cuComplex , float2 was manchmal gefährlich sein kann. (tatsächlich bin ich letztes Jahr auf dieses Problem gestoßen, und reinterpreter_cast war die Lösung).

Ich persönlich würde es aber vorziehen, alles nativer zu schreiben.

Und ich denke, wir brauchen wahrscheinlich einen Zeitrahmen oder eine Roadmap, und wir können jeden kleinen Teil aufgreifen und zusammenarbeiten, damit ich nicht selbst den Meister verfolgen muss, was völlig unmöglich ist ...

Als ich versuchte, das CPU-Backend zu implementieren, gab es ein ChangeLog . Ich klassifizierte Funktionen, die für komplexe Zahlen im Protokoll geändert werden müssen. Auf der Grundlage dieses Protokolls könnten wir eine Roadmap schreiben.

Außerdem muss ich, da mein Visum (von Australien) gerade abgelehnt wurde, ein Gap Year beginnen, wenn Sie jemanden brauchen, der weiter daran arbeitet, könnte ich mich für ein Praktikum bewerben.

Ich habe am letzten Tag viel darüber nachgedacht. Es ist ein bisschen traurig, dass wir Rogers Bemühungen nicht so zusammenführen konnten, aber ich dachte mir

"Wie können wir eine komplexe Tensor-Unterstützung aufbauen und gleichzeitig den Wartungsaufwand gering halten?"

Dies ist, was ich als effektiven Plan für das obige Ziel darlege:

  • Komplexe Tensoren sollten kein grundlegend neuer Tensortyp sein, wie sparse Tensoren. Das Hinzufügen eines grundlegenden Typs verursacht viel Wartungsaufwand und bereichsübergreifende Änderungen. Beim Wartungsaufwand geht es nicht um "wer pflegt die komplexen Bits?", sondern eher um "jetzt sollten sich alle Core-Entwickler dieser komplexen Art bewusst sein, wenn sie grundlegende Änderungen, ATen-Änderungen usw. vornehmen".

    • Stattdessen sollten sie immer [Tensor Shape x 2] oder [2 x TensorShape] sein, dh der Tensor sollte eine zusätzliche Dimension mit einer Größe 2 haben.

  • Komplexe Tensoren sollten eine kleine Datei / ein kleiner Ordner mit ca. 2.000 Zeilen einfachen C++ sein, die auf der ATen Tensor API aufbauen.

    • Wie beispielsweise https://github.com/pytorch/pytorch/issues/6514 vorschlägt, sollte eine komplexe Multiplikation als torch.stack([real1 * real2 - imag1 * imag2, real1 * imag2 + imag1 * real2], dim = -1) implementiert werden, wobei real1 = input1[:, :, :, ..., 0]

    • Dies schadet der Leistung: Ja, wir werden nicht so viel Leistung erzielen, als wenn wir alles inline machen würden. Die Frage ist jedoch: "um wie viel?". Ich denke, wir sollten eine um 20 % niedrigere Leistung im Austausch für eine gesunde und voll funktionsfähige + gepflegte komplexe Unterstützung anstreben.

    • Die am häufigsten verwendeten komplexen Funktionen können damit beginnen, dedizierte Kernel zu erhalten, sodass wir eingreifen, wenn die Leistung bei einer häufig verwendeten Funktion um mehr als 20 % beeinträchtigt wird.

Es muss [Tensor Shape x 2] sein, da BLAS, Cublas und MAGMA alle ihre eigenen komplexen Typen erwarten, die Byte-kompatibel zu Float2 sind. Auch Blas-, Cublas- und Magma-Aufrufe können nicht auf Python-Ebene behandelt werden.
Ich glaube nicht, dass es bei komplexer Multiplikation nur 20% sein werden, haben Sie nicht 4 vollständige Kopiervorgänge zusätzlich zu den Berechnungen für Real- und Image-Teil?
Wie auch immer, ich wäre immer noch froh, wenn ich nicht ständig Änderungen von master einmischen muss.

Stimmen Sie @PhilippPelz zu, wir könnten viel Leistung verlieren, da wir die komplexe Unterstützung von BLAS, Cublas und MAGMA verlieren werden. Aber ich bin mir nicht sicher. Um es jedoch klarzustellen, komplexe Tensor ist etwas völlig anderes als Sparse Tensor , die meisten Bibliotheken wie scipy.sparse und Julias SparseArrays behandeln Sparse Arrays als eine Zusammensetzung grundlegender mehrdimensionaler Arrays. Aber niemand behandelt ein mehrdimensionales Array mit komplexem Typ, indem er zwei echte Arrays zusammensetzt ... (niemand hier, ich meine Tensorflow, Arrayfire, Numpy und Julia). Obwohl in MXNet die FFT tatsächlich durch eine Zusammensetzung von zwei echten Tensoren erreicht wird, unterstützen sie keine Komplexe ... Es scheint, dass Tensorflow einen DataType als Wrapper um verschiedene Typen implementiert hat, einschließlich complex64 und complex128 siehe Typen.proto

Über den Leistungsverlust

Erstens haben die elementweisen Funktionen (Funktionen rufen map/reduce) keinen großen Leistungsverlust auf (zumindest wird der Speicher für diese Operationen zusammenhängend sein). Aber ich denke, wir sollten zuerst versuchen, einige BLAS-Funktionen zu bewerten, um zu sehen, ob eine Zusammensetzung von FloatTensor eine ähnliche Leistung wie Complex64Tensor auf der GPU hat und wie viel wir an Leistung mit a verlieren werden Entwurf einer Implementierung, wie:

  • gemm
  • gemv

Ein zusammengesetzter komplexer Tensor würde in etwa so aussehen (oder verwenden Sie einfach shared_ptr ):

class ComplexTensor {
    FloatTensor *real;
    FloatTensor *imag;
};

Wie ich jedoch im Nachteil des ersten Ansatzes erwähnt habe, sehen Funktionen wie __shfl_xxx auch wie ein Hindernis aus, wenn wir dies nativer machen wollen.

derzeit gibt torch.fft einen einzelnen Float-Tensor der Form [dim1, ..., dimN, 2] zurück

@ezyang , was ist der Zeitrahmen für die C10-Veröffentlichung? Das klingt nach einem sehr vernünftigen Punkt, um mit der Unterstützung von Komplexen im Master-Zweig zu beginnen.

@PhilippPelz Definitiv nicht für 0.4. Wir zielen intern auf den Juni ab und hoffen, dass das nicht zu lange dauert.

@ezyang du hast June erwähnt, hast du es geschafft, Unterstützung für komplexe Zahlen zu PyTorch hinzuzufügen?

Ich denke, er meinte C10, nicht komplexe Unterstützung. C10 wird das Hinzufügen von Komplexen erleichtern. So habe ich es verstanden.

Ja, C10 wird eine offene Registrierung beider Tensortypen und -funktionen haben. Das Hinzufügen eines komplexen Typs als separates Paket ist also viel einfacher.

Gibt es eine ETA für komplexe Zahlen? Bedeutet "viel einfacher" "wird wahrscheinlich schnell erledigt sein"?

@themightyoarfish mit viel einfacher, ich meine, dass wir nicht blockiert werden, was zum Pytorch-Meister geschoben werden kann. Wir haben keine voraussichtliche Ankunftszeit festgelegt. Ich werde die Arbeit auswerten, sobald wir eine offene Registrierung bei PyTorch erhalten haben.

@soumith brauchst du noch Leute, die daran arbeiten (komplexe Zahl)? Das PyTorch-Team wird komplexe Zahlen unterstützen? Ich kann im September einige Zeit damit verbringen, wenn Sie möchten, da ich QuCumber pflegen werde (es wird komplexe Zahlen stark verwenden).

@ Roger-luo ja. Ich wollte mich an Sie wenden, sobald wir eine offene Registrierung im PyTorch-Backend verfügbar haben und wir Details ausarbeiten können.
@ezyang werden wir bis September eine offene Typenregistrierung haben?

@soumith Cool, zu Ihren Diensten.

Wir können es möglich machen. (Wir werden nicht das „vollständige“ neue System an Ort und Stelle haben, aber solange wir die Dinge so einrichten, dass es umgestaltbar ist, können wir es weiter vorantreiben, wenn neue Entwicklungen stattfinden. Es wird ein guter Testfall für das neue Open sein Registrierung. Ich kann dafür sorgen, dass dies geschieht.)

@ezyang irgendwelche Notizen bis jetzt? Ich könnte es aber lesen, bevor ich daran arbeite. Seit dem letzten Mal scheint sich einiges geändert zu haben.

@Roger-luo @PhilippPelz Auch bei der Implementierung komplexer Tensoren möchte ich dir helfen. Ich brauche es auch für meine PhD-Untersuchungen.

@alexgomezalanis Vielleicht könnten wir einen Kanal haben, um in Ruhe zu diskutieren, ich habe gerade einen Kanal mit dem Aufruf #complex-numbers erstellt. Aber ich werde erst im September damit anfangen (muss noch an meinem Julia-Code arbeiten ...)

Übrigens, es scheint sich seit dem letzten Mal sehr verändert zu haben. Ich werde etwas Zeit nutzen, um aufzuholen, bevor ich es in die Hände bekomme.

@alexgomezalanis Ich kann nicht. Sie müssen zuerst dem Workspace von Pytorch auf Slack beitreten. Ich kann Sie nicht finden. Bitte senden Sie eine E-Mail an die Adresse: [email protected] , um eine Einladung zu erhalten.

@Roger-luo @alexgomezalanis Schön , wieder Leben in der komplexen Tensor-Frage zu sehen. Ich kann auch anbieten, mitzumachen, aber das wird realistischerweise nicht vor Ende September/Anfang Oktober passieren. Was einige Kommentatoren zu diesem Thema betrifft, wäre die Unterstützung komplexer Tensoren für mein Promotionsprojekt sehr hilfreich.

Ich habe letztes Jahr auch versucht, meine Recherchen zu retten 😏… aber jetzt möchte ich einfach nur meinen alten 1w+-Lokcode wieder zum Leben erwecken. 🤣 lass uns locker chatten!

:) Ja, lass uns locker plaudern. Hab gerade die Einladung im Mailordner gefunden.

Das in Arbeit befindliche Plugin (für CPU nur kurzfristig) ist hier: https://github.com/Roger-luo/pytorch-complex

Bitte zögern Sie nicht, mir Ausgabe und PR zu geben.

Die Hinweise zur Durchführung der komplexen Implementierung habe ich oben in dieser Ausgabe gepostet.

Ich habe vor kurzem angefangen, PyTorch zu verwenden, und ich liebe es absolut – es ist so viel angenehmer zu verwenden als TensorFlow. Komplexe Tensorunterstützung ist jedoch ziemlich kritisch für meine Forschung (optische neuronale Netze). Wird daran noch aktiv gearbeitet? Wenn ja, kennt jemand einen (lockeren) Zeitrahmen für die Unterstützung komplexer Tensoren?

Ich würde gerne dabei helfen, wo ich kann, aber ich bin relativ neu bei PyTorch, daher habe ich noch keine gute Vorstellung davon, wie groß das Unterfangen dieses Features ist. Einige meiner Laborkollegen haben auch großes Interesse an der Unterstützung komplexer Tensoren bekundet (in der Physik könnte das Hinzufügen von Torch fast zu einem Drop-in-GPU-beschleunigten Ersatz für NumPy werden) und könnten ebenfalls bereit sein, zu helfen, wenn dies bedeutet, komplexe Unterstützung zu erhalten nahe Zukunft.

Hallo @bencbartlett

Ich versuche immer noch, langsam daran zu arbeiten.... aber ich bin derzeit auch nur Student (mit einer ziemlich instabilen Situation), was bedeutet, dass ich nicht Vollzeit daran arbeiten kann, sondern nur in der Freizeit. (Ich implementiere meinen forschungsbezogenen Code in Julia aus dem letzten Jahr, was bedeutet, dass nur unser Legacy-Paket eine bessere Unterstützung komplexer Zahlen von Fackel benötigt.).

Wenn komplexe Zahlen für Sie von entscheidender Bedeutung sind und dringend benötigt werden, würde ich vorschlagen, Folgendes zu versuchen:

https://github.com/PIQuIL/QuCumber/blob/master/qucumber/utils/cplx.py

Es ist super langsam ... aber es funktioniert zumindest. Oder ich hatte eine C-Version im alten TH-Stil.

Dies wird kein kleines Projekt sein, das in ein paar Tagen erledigt werden kann. Daher kann ich keinen bestimmten Zeitrahmen für eine vollständige Funktionsunterstützung mit komplexem Wert auf CPU oder CUDA garantieren.

Ich würde Ihnen jedoch gerne dabei helfen, mit mir gemeinsam daran zu arbeiten. Ich würde Ihnen vorschlagen, mit dem Versuch zu beginnen, die Probleme zu lösen, die ich im Erweiterungsrepo gepostet habe. Und bitte zögern Sie nicht, mich per Slack oder E-Mail oder Issue zu fragen, wenn Sie Fragen haben (da es noch nicht viele Dokumente gibt).

Leider habe ich noch keinen Zugriff auf PyTorch Slack. (Ich habe zweimal per E-Mail um eine Einladung gebeten, aber keine Antwort erhalten.) Könnte mich jemand einladen? ([email protected])

@Roger-luo Ich werde auf jeden Fall einen Blick auf Ihren Fork werfen, aber ich kann nicht versprechen, dass ich Ihnen viel helfen werde - mein C++ ist verrostet und wie Sie bereits sagten, ist es schwierig, Zeit zu finden, um als Schüler. Die QuCumber-Dienstprogramme sind nett, aber leider wären sie für mich nicht sehr hilfreich: Bis komplexe Tensoren GPU-unterstützt sind oder von autograd und Torch.nn unterstützt werden, bieten sie nicht viel Nutzen über das hinaus, was NumPy bieten kann.

@soumith @ezyang Es wäre großartig, wenn das PyTorch-Team mehr Aufmerksamkeit dafür bekommen würde! Die komplexe Unterstützung scheint ein wichtiges Merkmal für eine allgemeine Tensorbibliothek zu sein, sie ist praktisch unerlässlich in der Physik, und speziell in ML gab es in den letzten Jahren ein schnell wachsendes Interesse an komplexwertigen Modellen.

Der Ansatz von @bencbartlett QuCumber kann auf GPU mit AD verwendet werden ... es ist nur super langsam ... Ich meine, wenn Sie nur dieses AD wollen, können Sie es vielleicht verwenden.

Ja, ehrlich gesagt verwende ich eine leicht modifizierte Version von https://github.com/FluxML/Flux.jl und einige meiner eigenen Pakete in Julia für die Recherche (ich brauche in manchen Situationen auch komplexes AD auf der GPU mit Tensoren ). Das source2source AD-Paket Zygote.jl kann AD auf komplexen Tensoren ausführen, befindet sich jedoch in einem sehr frühen Stadium, das möglicherweise Segmentfehler aufweist. Das Ökosystem ist im Vergleich zu Fackel noch nicht so stabil, ich muss diese Implementierung manchmal ein wenig für den Eigengebrauch hacken ... Aber es funktioniert einfach im Grunde für das, was ich für die Forschung in der Quantenphysik brauche. Ich kann auch komplexe Tensoren auf der GPU haben.

Ich glaube nicht, dass Unterstützung für komplexe Werte für torch.nn erforderlich ist. Wir müssen möglicherweise nur ein paar Definitionen für autograd hinzufügen, sobald der komplexe Tensor funktionsfähig ist, da Dinge wie lineare Ebenen gleich bleiben können . Und einige Aktivierungsfunktionen haben möglicherweise keine Standarderweiterung im Hilbert-Raum ... (Sie können den Blogbeitrag meines Mitarbeiters @GiggleLiu überprüfen.)

Für die Pytorch-Complex-Erweiterung bin ich mir nicht sicher, wann wir volle Unterstützung mit AD auf der GPU erhalten können ... das scheint mir noch ziemlich weit zu sein. Ich würde sagen, die CPU-Implementierung wird einige Zeit durchlaufen, die Patches im Hauptbaum erfordert (z. B. Type Promotions, Simd-Unterstützung usw.), dies könnte auch mit der kommenden ATen-Implementierung in C++ zusammenhängen und TH loswerden usw., und dann können wir Operatoren für komplexe Tensoren schneller hinzufügen.

Ich kann mich für Praktika im Frühjahr bewerben (worüber ich @ezyang gerade gefragt habe). So kann ich vielleicht mehrere Monate in Vollzeit daran arbeiten, bevor ich mit meiner Promotion beginne. Mal sehen.

Inzwischen habe ich meine eigene Version der komplexen Multiplikation implementiert. Wenn ich es jedoch profiliere, kommt es vor, dass eine beträchtliche Menge Zeit vergeht an: Torch._C_._cuda_isDriverSufficient

image

Hast du eine Ahnung warum? Wenn Sie eine bessere Implementierung der komplexen Multiplikation kennen, lassen Sie es mich bitte wissen. Irgendwie scheint meine Version (obwohl optimiert auf die Anzahl der Multiplikationen: 3 statt 4) relativ langsam zu sein, zB ist irfft des Out-Tensors 10x schneller als meine elementweise Multiplikation. Wird die komplexe Multiplikation auf der C++-Ebene von PyTorch unterstützt?

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)

Wir versuchen, es von C++ aus zu unterstützen. siehe Beitrag ganz oben. Wenn Sie die Erweiterung kompilieren können, sollte sie zumindest im Moment für die Skalarmultiplikation funktionieren ....

Ihre Implementierung ähnelt der, die wir in QuCumber haben. Es kann viele zusätzliche GPU-Threads aufrufen, wenn Sie nicht den richtigen cuda-Kernel für komplexe Zahlen aufrufen. Und Sie könnten SIMD verlieren, wenn Sie kein C++-Backend als Unterstützung in Python haben.

Ich würde vorschlagen, dass Sie nvprof ausführen, um weitere Details zu erhalten.

@Roger-luo @apaszke @soumith Danke für diesen Thread übrigens. Ich habe einen grundlegenden komplexen Tensor implementiert, der aus Unterklassen-Torch.Tensor zusammengehackt wurde.

Ich betrachte die erste Hälfte als real, die zweite als imaginär und habe meine eigenen Grundrechenarten und einige andere, die ich für meine Forschung benötige, implementiert.

Ich habe gegen Tensorflow und numpy verifiziert. Die Farbverläufe und alle Operationen, die ich implementiert habe, stimmen mit ihren Ausgaben überein!

Es ist nur als Überbleibsel gedacht, bis PT komplexe Tensoren vollständig unterstützt.

Merkmale:

  1. Tests implementiert.
  2. Pypi unterstützt (dh: Pip-Installation)
pip install pytorch-complex-tensor

https://github.com/williamFalcon/pytorch-complex-tensor

Danke @williamFalcon !

Irgendein Update eins davon? Ich frage mich nur, ob es einen Plan geben wird, Unterstützung für komplexe Typen in die Pytorch zu integrieren.

Hallo, @whmrtm

@ezyang arbeitet an https://github.com/Roger-luo/pytorch-complex/issues/4 Oder wer auch immer daran interessiert ist, könnte uns helfen, es zum Laufen zu bringen. Dieses Problem löst einige grundlegende Broadcast-Probleme (dann können Sie viele Funktionen verwenden, nachdem dieses Problem gelöst wurde). Bitte zögern Sie nicht, PR zu machen oder mich zu bitten, Sie als Mitarbeiter hinzuzufügen.

Ich werde bis zum Sommer an nichts arbeiten können, muss eine neue Veröffentlichung für unser eigenes Paket fertigstellen.

Hallo, @whmrtm

@ezyang arbeitet an Roger-luo/pytorch-complex#4 Oder wer auch immer daran interessiert ist, könnte uns helfen, es zum Laufen zu bringen. Dieses Problem löst einige grundlegende Broadcast-Probleme (dann können Sie viele Funktionen verwenden, nachdem dieses Problem gelöst wurde). Bitte zögern Sie nicht, PR zu machen oder mich zu bitten, Sie als Mitarbeiter hinzuzufügen.

Ich werde bis zum Sommer an nichts arbeiten können, muss eine neue Veröffentlichung für unser eigenes Paket fertigstellen.

Danke für das Update, ich werde sehen, was ich tun kann.

Hallo @Roger-luo

Kann ich auf den Slack-Kanal zugreifen, der sich auf das Supportthema für komplexe Tensoren bezieht ([email protected])? Ich habe eine E-Mail um eine Einladung gebeten, aber es ist noch nichts passiert. Im Moment versuche ich herauszufinden, wo ich anfangen kann, zu diesem Problem beizutragen. Ich denke, https://github.com/Roger-luo/pytorch-complex/issues/4 ist jetzt ein aktueller Einstiegspunkt?

@beconstant ja, das ist der Ausgangspunkt, dies sollte einige Broadcast-Funktionen zum Laufen bringen, aber ich weiß nicht, warum es einen Type-Promotion-Fehler auf cuda auslöst, es funktionierte auf der CPU. (Obwohl wir nicht beabsichtigen, cuda von vornherein zu unterstützen, würde dies zu einem Build-Fehler führen.)

Ich kann Ihnen keine Einladungs-E-Mail senden (ich habe keinen Zugriff). Ich denke, Sie sollten dem offiziellen Leitfaden von Pytorch folgen, um sich Slack anzuschließen. Aber wir können immer in der Ausgabe/PR diskutieren.

@ Roger-luo ok, verstanden :)

Lasst mich wissen, wenn ihr Hilfe braucht. Ich beginne mit dem Erstellen der angegebenen Pytorch-Version. Irgendwelche Fortschritte bei pytorch-complex/issues/4 ?

Lasst mich wissen, wenn ihr Hilfe braucht. Ich beginne mit dem Erstellen der angegebenen Pytorch-Version. Irgendwelche Fortschritte bei pytorch-complex/issues/4 ?

@dylanbespalko Hallo, ich brauche dringend Pytorch, das in einer Complex-Valued-Version implementiert ist.
Vielen Dank für Ihre Beiträge.

Mit freundlichen Grüßen,
Zellar209

Hallo @Zellar209 ,

Ich habe das Gefühl, dass @ezyang hart an einem der größeren Probleme arbeitet ( pytorch-complex/issues/4 ). Ich habe jetzt ein AMD-System und in 3 Wochen ein Nvidia-System, mit dem ich die GPU-Unterstützung hochfahren kann.

Ich denke, das Problem liegt nur an der Änderung der ursprünglichen Typpromotion, die CUDA unterbricht, solange diese PR gelöst ist, arbeiten zumindest einige Operatoren an der CPU, wir haben noch überhaupt keine CUDA-Unterstützung ...

IMHO Ich denke, wir sollten uns zuerst auf die CPU konzentrieren und die Dinge zum Laufen bringen und dann die GPU später in Betracht ziehen.

Nur die CPU-Unterstützung ist in Ordnung. Wird dieses Typ-Promotion-Problem ( pytorch-complex/issues/4 ) intern von fb behandelt? Ist es in Ordnung, extern daran zu arbeiten?

Hallo @dylanbespalko; Ich habe @Roger-luo gesagt, dass ich mich damit befassen werde (weil ich wahrscheinlich am besten in der Lage war, herauszufinden, was das Problem ist), aber ich hatte noch keine Zeit, mir das anzusehen. Wenn Sie herausfinden möchten, wie Sie das Problem beheben können, berate ich Sie gerne.

Hallo @Zellar209 ,

Ich habe das Gefühl, dass @ezyang hart an einem der größeren Probleme arbeitet ( pytorch-complex/issues/4 ). Ich habe jetzt ein AMD-System und in 3 Wochen ein Nvidia-System, mit dem ich die GPU-Unterstützung hochfahren kann.

Ja, ich brauche jetzt keine GPU, ich benutze das MAC-System. Aber ich hatte einige Fehler beim Erstellen dieses Projekts.

Hallo @Zellar209 , könntest du posten, was du in der Ausgabe von pytorch-complex bekommst? Ich denke, mit dem neuen Xcode von Mac stimmt etwas nicht, was das Erstellen erschwert. Aber die Leute brauchen noch mehr Fehlermeldungen, um herauszufinden, warum.

Ich habe nach dem Betriebssystem und der Fehlermeldung gefragt, aber Sie haben nicht geantwortet ...

Hallo @dylanbespalko; Ich habe @Roger-luo gesagt, dass ich mich damit befassen werde (weil ich wahrscheinlich am besten in der Lage war, herauszufinden, was das Problem ist), aber ich hatte noch keine Zeit, mir das anzusehen. Wenn Sie herausfinden möchten, wie Sie das Problem beheben können, berate ich Sie gerne.

Vielen Dank für Ihre baldige Antwort.

1. Wenn ich „python setup.py install“ mit gcc (Standard) ausführe, erhalte ich Fehler wie diese:

Erstellung der Erweiterung „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: Fehler: nicht erkannte Befehlszeilenoption „-stdlib=libc++“

Fehler: Befehl „gcc“ ist mit Exit-Status 1 fehlgeschlagen

2. Wenn ich clang zum Kompilieren verwende, sind die Fehler:

In Datei enthalten von src/module. cpp:2 :
In der Datei enthalten von src/CPUComplexType.h:60:
src/CPUComplexTypeImpl.h:102:105: Warnung: „IntList“ ist veraltet [-Wdeprecated-declarations]
Tensor & CPUComplexType::set_(Tensor & self, Speicherquelle, int64_t storage_offset, IntList-Größen, IntList-Schritte) const {
^
/anaconda3/lib/python3.6/site-packages/torch/include/c10/util/ArrayRef.h:273:7: Hinweis: „IntList“ wurde hier ausdrücklich als veraltet markiert
mit IntList C10_DEPRECATED_USING = ArrayRef;
^
In Datei enthalten von src/module. cpp:2 :
In der Datei enthalten von src/CPUComplexType.h:60:
src/CPUComplexTypeImpl.h:105:76: Fehler: kein Mitglied namens „scalarTypeToDataType“ im Namespace „at“
auto source_ = selected_storage(source,"source",2, DeviceType::CPU, at::scalarTypeToDataType(CPUComplexTypeInfo::scalar_type));
~~~~^
7 Warnungen und 2 Fehler generiert.

Fehler: Befehl 'clang' ist mit Exit-Status 1 fehlgeschlagen

Ich kann es nicht beheben. Ich hoffe sehr, dass ihr mir helfen könnt!

Hallo Leute,

Vielen Dank für Ihre Rückmeldung. Ich denke, ich kann die Woche damit verbringen, mich damit zu befassen. Bisher habe ich den Pytorch-Komplex von @ Roger-luo wie folgt kompiliert:

@Zellar209 : Ich habe meine Umgebungsvariablen angehängt, die unter macOS 10.13 ausgeführt werden.

  1. Löschen Sie die vorhandene Pytorch-Distribution wie folgt
    conda pytorch deinstallieren
    Pip Fackel deinstallieren
    Pip Uninstall Torch # Führen Sie diesen Befehl zweimal aus
    python setup.py sauber
    Löschen Sie den Torch-Ordner im Ordner python site-packages, falls vorhanden.
    Benennen Sie den vorherigen Pytorch-Quellordner um (oder löschen Sie ihn) (etwas bezog sich darauf).

  2. Installieren Sie die PyTorch-Revision 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
  1. Installieren Sie pytorch-complex
    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)
  1. Erstellen Sie einen komplexen Tensor
   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:

Alles für die Typförderung für Tensoroperationen scheint in c10/core/ScalarType.h erledigt zu sein
Ich habe den Fehler AT_ERROR("promoteTypes with complex numbers is not handled yet; figure out what the correct rules should be”); gefunden
Es sieht so aus, als müsste ich in dieser Tabelle einen Eintrag für c8 und c16 hinzufügen.
Hat das etwas mit 9515 zu tun? Ich denke, das ist nur zum Aufrufen von numpy-Funktionen.
Ist das ein guter Anfang?

9515 ist nicht verwandt. Das Korrigieren dieses Codepfads in ScalarType.h ist jedoch ein guter Ausgangspunkt.

Ich habe den Codepfad in ScalarType.h korrigiert
BinaryOps (add, sub, mul, div) funktioniert, aber nur, wenn beide Argumente Tensoren sind.
Einige andere seltsame Probleme, aber ich muss mir das noch etwas genauer ansehen.

@dylanbespalko Ich habe hier Type Promotions hinzugefügt: https://github.com/pytorch/pytorch/pull/11641

Sie könnten das einfach kopieren, aber das Problem ist, dass dies CUDA irgendwie kaputt macht.

IIRC, es gab einen Drahtfehler aufgrund der gcc-Version. Da hatte ich einige Workarounds.

Ah, danke @Roger-luo. Ich habe mir die Kommentare von #11641 angesehen . Ich werde den Code morgen besser kopieren.

Woher weiß ich, dass CUDA defekt ist, wenn ich kein CUDA-Gerät habe? Ich nehme an, der CI wird es mir sagen?

Ja, sobald Sie eine PR einreichen, wird Ihnen mitgeteilt, welche defekt ist. Und wenn alles durchgeht, könnten wir das einfach zusammenführen und die Dinge zum Laufen bringen.

Ok, dann fange ich an, PRs einzureichen, damit ich weiß, wann es passiert.

@dylanbespalko Hallo, es scheint noch einige Fehler in deiner Umgebung zu geben?
Wenn Sie es beheben, teilen Sie es uns bitte mit. Vielen Dank.

Hallo Leute,

Ich habe versucht, mehrere PRs durchzuführen, nachdem ich mehrere Commits von @Roger-luo kopiert hatte. Leider habe ich derzeit keine CUDA-GPU und die CI-Maschinen mit CUDA werden nicht initialisiert. Ich kann den CUDA-Testfehler im Moment nicht reproduzieren, also werde ich in ein paar Wochen darauf zurückkommen, wenn ich lokal auf dieser GPU laufen kann. Sieht zumindest vielversprechend aus.

@ezyang , @Roger-luo

Ich habe mir Rogers PR #11641 angesehen :

  • Es wird auf meiner CUDA 9.0-Maschine erstellt und ausgeführt
  • Es kann nicht auf CI-Computern erstellt werden, auf denen CUDA 9.0 ausgeführt wird

Ich habe mir auch einige der jüngsten PyTorch-Entwicklungen angesehen:

  • Eine Präsentation von @ezyang , die beschreibt, wie eine C++/CUDA-Erweiterung geschrieben wird, die ein benutzerdefiniertes Gerät/Layout/dtype definieren kann.

    • Ein neueres PR #21964 , das „das ComplexHooksInterface entfernt“, aber eine C++-Erweiterung für komplexe Zahlen definiert, die sich unter pytorch/test/cpp_extensions/complex_registration_extension.cpp befindet

Es scheint mir, dass eine neue Erweiterungsfunktion "außerhalb des Baums" entwickelt wird, die es mir ermöglichen würde, die Unterstützung komplexer Zahlen zu untersuchen, ohne den Rest der Pytorch zu beschädigen. Mein Ziel ist:

  1. Definieren Sie komplexe CPU-Unterstützung ohne AVX.
  2. Definieren Sie komplexe CUDA-Unterstützung mit Thrust.

@ezyang
Können Sie einen voraussichtlichen Zeitplan für diese nicht im Baum vorhandene Geräte-/Layout-/Dtype -Erweiterung angeben, die Sie vorgestellt haben? Können wir diese Funktion in den nächsten 3 Monaten erwarten?

@ezyang

Können Sie die Unterstützung komplexer Zahlen auf der CPU ohne AVX/SSE-Unterstützung zusammenführen? Ich beabsichtige, Folgendes in separaten Merge-Requests einzureichen:

  • [ ] Komplexe Unterstützung von CPU-BinaryOp-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU TensorFactories hinzugefügt
  • [ ] Komplexe Unterstützung von CPU FillKernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-Range-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-Unary-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-Vergleichskernen hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-TensorCompare-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU ReduceOp Kerneln hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-PointwiseOps-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-LearOps-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-LinearAlgebraOps-Kernels hinzugefügt
  • [ ] Komplexe Unterstützung von CPU-SpectralOps-Kernels hinzugefügt

Ich plane, dies in den nächsten Tagen über Intel/Arm-CPUs testen zu lassen.

@ezyang ,

Ich untersuche Operationen wie fft() und var() , bei denen die Implementierung komplexer Zahlen die Tensordaten in einen doppelten Tensor der Form umwandeln muss: (complex_shape, 2) . Dies funktioniert nicht mit vorhandenen Tensormethoden:

  1. 'tensor.to(torch.float64): behält nur den Realteil und gibt einen Tensor mit der gleichen Form zurück.
  2. 'tensor.view(new_shape): neue Form muss die gleiche Anzahl von Elementen haben.

Offensichtlich kann ich etwas Ineffizientes tun wie:

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]

Offensichtlich ist das das Erstellen von Kopien, wenn ich nur static_cast<double> brauche und die Form des Tensors in (old_shape, 2) ändere. Haben Sie Vorschläge, wie Sie dies tun können?

Außerdem gibt es einen Hack in numpy, mit dem Sie dies tun können:

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

Die Möglichkeit, dtype festzulegen, funktioniert in dieser Situation wirklich, kann jedoch unvorhersehbar sein.

Einige zusätzliche Informationen zur Interpretation einer komplexen Zahl als Array reeller Zahlen der Länge 2. Folgendes gilt in C++11.

Für jeden Zeiger auf ein Element eines Arrays aus komplexen Zahlen p und jeden gültigen Array-Index i reinterpret_cast(p)[2 i] ist der Realteil der komplexen Zahl p[i] und reinterpret_cast(p)[2 i + 1] ist der Imaginärteil der komplexen Zahl p[i]. (Seit C++11)

Ich denke, das bedeutet, dass es möglich ist, einen complex_tensor in einen real_tensor mit shape (complex_shape, 2) umzuwandeln und dann eine Operation durchzuführen, ohne real() und imag() aufzurufen, die neuen Speicher zugewiesen haben.

@dylanbespalko Ich hatte Angst davor, wann Sie danach fragen würden :) Die std::complex -Garantie bedeutet, dass Sie den Datenzeiger std::complex<float>* sicher in float* umwandeln können, wenn Sie den Datenzeiger std::complex<float>* haben (murmeln Sie striktes Aliasing) und geben Sie es dann an das fft-Ding weiter, das Sie verwenden. Wenn Sie nur fft/var implementieren müssen, wo Sie diesen Low-Level-Rep weitergeben können, ist das am einfachsten.

Wenn Sie jedoch einen komplexen Tensor buchstäblich als Float-Tensor neu betrachten müssen, sind wir etwas in der Klemme, da es in PyTorch heute keinen Präzedenzfall dafür gibt. Storage dtype stimmte immer mit Tensor dtype überein. Wenn Sie also einen komplexen Speicher erstellen, gibt es keine Möglichkeit, ihn als Float-Speicher zu betrachten.

Ein Gedanke, den ich hatte, war vielleicht, dass wir diese Invariante lockern sollten. Die Idee ist:

  1. Wir ordnen Speicher immer dem betreffenden "nicht vektorisierten" Typ zu. Also für einen Komplexwir weisen einen Float-Tensor zu.
  2. Tensor-dtype darf von Speicher-dtype abweichen, aber nur als vektorisierte Variante des zugrunde liegenden Typs

Ich bin mir nicht sicher, wie viel Code wir ändern müssten, um diese Invariante zu erreichen.

@ezyang ,

Ja, das war unvermeidlich...

Wenn Sie nur fft/var implementieren müssen, wo Sie diesen Low-Level-Rep weitergeben können, ist das am einfachsten.

Ja, das ist in vielen Fällen möglich. Können Sie ein Code-Snippet bereitstellen, wie Tensordaten als std::vector interpretiert werden?

Wenn Sie jedoch einen komplexen Tensor buchstäblich als Float-Tensor erneut betrachten müssen, ....

Ich würde mir vorstellen, dass es selten ist, einen Tensor mit einem anderen dtype anzuzeigen. Ich habe eine set_dtype() Methode für Tensor implementiert, aber ich habe einige Fehler bekommen. Ich habe auch die Schritte nicht aktualisiert, um die Änderungen in der Form widerzuspiegeln. Ich bin mir nicht sicher, warum die Einstellung von dtype in numpy funktioniert (ist es ein Zufall?), aber wenn Sie Daten in einen Digital-Analog-Konverter (DAC) hochladen, wird oft erwartet, dass die realen/imaginären Daten verschachtelt sind. Vielleicht würde dies die Notwendigkeit motivieren, den Tensor-Dtype vom Speicher-Dtype zu entkoppeln, wie Sie vorgeschlagen haben.

Ich werde das vorerst vermeiden. Ich bin mir sicher, dass es für mich andere Leistungsengpässe gibt.

Ja, das ist in vielen Fällen möglich. Können Sie ein Code-Snippet bereitstellen, wie Tensordaten als std::vector interpretiert werden?

Nicht gerade ein std::vector, aber ich stelle mir so etwas vor:

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;

Ich habe eine set_dtype()-Methode für Tensor implementiert, aber ich habe einige Fehler bekommen. Ich habe auch die Schritte nicht aktualisiert, um die Änderungen in der Form widerzuspiegeln.

Ja, das ist wahrscheinlich eine schlechte Idee, wenn Sie nicht auch die Schritte korrigieren. Außerdem bin ich kein großer Fan von Tensoren, die in andere dtypes umgewandelt werden; besser alles fehl am Platz :)

Wenn Sie jedoch Daten in einen Digital-Analog-Wandler (DAC) hochladen, erwartet dieser häufig, dass die realen/imaginären Daten verschachtelt sind. Vielleicht würde dies die Notwendigkeit motivieren, den Tensor-Dtype vom Speicher-Dtype zu entkoppeln, wie Sie vorgeschlagen haben.

Ja, letztendlich ist dies das Richtige, aber ich stimme zu, dass es einfacher ist, dies jetzt nicht zu tun.

@ezyang ,

Ich fange an, mit der CUDA-Unterstützung für komplexe Zahlen herumzuspielen.

Es gibt zwei binärkompatible Optionen:

  1. cuComplex : Sehr einfache add-, sub-, mul-, div-, real-, imag-Unterstützung.
  2. throw::complex : Drop als Ersatz für std::complex , der Host- und Gerätespeicherzuordnung unterstützt.

Der Thrust::complex-Container scheint der richtige Weg zu sein. Die Thrust::Complex-API schlägt vor, dass thrust::complex<T> -Container auf dem Host- und Gerätespeicher zugewiesen werden können, während die std::complex<T> nur auf dem Host-Speicher zugewiesen werden können:

__host__ __device__     thrust::complex< T >::complex (const complex< T > &z)  //thrust container
__host__    thrust::complex< T >::complex (const std::complex< T > &z) //stl container.
  1. Bedeutet dies, dass AT_DISPATCH_COMPLEX_TYPES using scalar_t = thrust::complex<double> anstelle von using scalar_t = std::complex<double> setzen sollte?

  2. Wie ruft Pytorch automatisch CUDA-Äquivalente von std::log für echte Datentypen auf? Woher weiß ich, dass es ein CUDA-Äquivalent eines mathematischen Kernels gibt?

  1. Ich denke, die Schwierigkeit bei der universellen Verwendung thrust::complex<double> für CPU und CUDA besteht darin, dass wir nicht wirklich gegen Schub bauen, wenn Sie nur einen CPU-Build machen. Ich denke, es gibt eine Reihe von Optionen; Wir könnten unseren eigenen komplexen Typ würfeln (ähnlich wie wir unseren eigenen halben Typ würfeln), oder Sie könnten einfach Ihren Weg zum Sieg neu interpretieren, da std::complex<> so definiert ist, dass es ein bestimmtes binäres Layout hat. Es liegt an Ihnen, aber es scheint im Moment einfacher zu sein, das Casting zwischen den Typen neu zu interpretieren.
  2. Wir haben mathematische Überladungen in THCNumerics.cuh, beantwortet das Ihre Frage?

@iotamudelta hat ein Problem mit der C++11-Compliance in #29547 gemeldet

std::real ist nur constexpr von C++14

Wenn ich das richtig verstehe, muss std::real() ein constexpr sein, damit der hcc-Compiler die Anweisung für __device__ kompilieren kann.

Mögliche Lösungen:

  1. Finden Sie eine andere Methode oder Funktion, um complex<double> in double umzuwandeln:
  1. Finden Sie einen Weg, um die Funktion zu umschließen:

    • Die meisten Aufrufe von std::real erfolgen in aten/src/ATen/native/cpu/zmath.h . Beispiel: inline durch constexpr ersetzen:

      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)

Dies wird nicht kompiliert, da es immer noch einen verschachtelten Aufruf von std::real() gibt, der kein constexpr ist.

3. Wenn ich std::complex verwende::real() statt std::real() scheint C++11-kompatibel zu sein.

  1. Ich denke, Sie sagen, dass dieser Code, egal was ich tue, bis C ++ 14 UB ist. Gibt es eine andere Möglichkeit, std::complex<double> in double umzuwandeln, die Ihre Anforderungen erfüllen würden?

@iotamudelta , @bddppq , @ezyang ,

Ich habe Unterstützung für komplexe UnaryOps und BinaryOps auf der CUDA-Thrust::complex-API hinzugefügt, aber ich muss ein paar Fragen stellen, bevor ich sie einreiche.

Ich habe eine Vorlagenfunktion definiert, die es Ihnen ermöglicht, die Datentypen „thrust::complex“ beim Umgang mit komplexen Zahlen zu verwenden.
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

Dann in aten/src/ATen/native/cuda/BinaryOpsKernel.cu
Ersetzen:

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;
    });
  });
}

Mit:

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;
    });
  });
}

Fragen

  1. @ezyang : Für nicht komplexe Zahlen sind skalar_t und Schub_t vom gleichen Typ. Vielleicht könnte ich den Variablennamen thrust_t durch etwas ersetzen, das für nicht komplexe Zahlen freundlicher ist, wie z. B. scalar_t_c ?
  2. Die Schubbibliothek scheint im Code weit verbreitet zu sein:
    a) @bddppq : Gibt es einen Grund, warum ich cuComplex anstelle von thrust::complex verwenden sollte?
    b) @iotamudelta : Hüftstoß wurde in ROCm2.7 entfernt. Sollte ich stattdessen hip_complex verwenden?
    throw::complex scheint mehr Funktionalität zu unterstützen als cuComplex .

Bitte sag mir was du denkst.

@iotamudelta

Ich habe die Diskussion über std::real() aktualisiert. Können Sie bestätigen, dass std::complex::real() würde das Problem beheben.

Hallo @dylanbespalko ,

Ich denke, worüber sich @iotamudelta beschwert, ist, dass dem cast_and_store für komplexe Typen ein C10_HOST_DEVICE fehlt, dies wäre ein UB, wenn dieser Codepfad jemals auf der GPU ausgeführt wird.

Derzeit wird dieses Dienstprogramm für dynamisches Casting nur in GPU TensorIterator verwendet, und es wird nur verwendet, wenn es eine Typförderung gibt. Aus dem Grund, dass Komplex derzeit nicht auf der GPU unterstützt wird, hat cast_and_store für komplexe Typen derzeit nicht den Qualifizierer C10_HOST_DEVICE und verwendet std::real , was für einen Host völlig in Ordnung ist. nur Funktion. Hier gibt es kein UB, weil es nicht verwendet wird und Sie sich um nichts kümmern müssen.

Da Sie jedoch der GPU Unterstützung für Komplexe hinzufügen möchten, wird Komplex durch Typförderung unterstützt, wie wir in https://github.com/pytorch/pytorch/blob/master/c10/core/ScalarType.h#L398 sehen können - L420, müssen Sie bei diesem Codepfad sehr vorsichtig sein, und es gibt einige Änderungen, die Sie möglicherweise vornehmen müssen, damit er funktioniert:

Natürlich müssen Sie C10_HOST_DEVICE hinzufügen, wie es @iotamudelta in https://github.com/pytorch/pytorch/pull/29547 tut, aber das reicht nicht aus, da einfach C10_HOST_DEVICE hinzugefügt werden ohne andere Änderungen ist immer noch UB auf C++11, wie von @iotamudelta erwähnt, eine gute Lösung könnte das sein, was Sie erwähnt haben: Verwenden Sie std::complex::real() , um die std::real $ zu ersetzen.

Aber darüber hinaus, wenn Sie sich die Datei https://github.com/pytorch/pytorch/blob/master/c10/util/TypeCast.h ansehen, sehen Sie in fetch_and_cast etwas wie:

#ifndef C10_HOST_DEVICE
    AT_FORALL_COMPLEX_TYPES(FETCH_AND_CAST_COMPLEX_CASE)
#endif

Dieser Codepfad ist auf der GPU deaktiviert. Sie müssen es aktivieren und zum Laufen bringen.

Außerdem habe ich keine Konvertierung zwischen complex<float> und complex<double> innerhalb fetch_and_cast und cast_and_store . Möglicherweise müssen Sie dafür auch die Konvertierung hinzufügen. Stellen Sie sicher, dass Sie die Abdeckung dieser Funktionen aller dtypes gründlich testen.

cc: @ezyang und @bddppq

Auch @dylanbespalko , bitte setzen Sie mich auf CC, wenn Sie Änderungen an TypeCast.h in Ihrer PR vornehmen.

OK, ich muss ein paar kleine Dinge mit torch.real() und torch.imag() auf ARM reparieren, also werde ich TypeCast.h und einige andere reparieren, wenn ich schon dabei bin. Ich cc euch auf der PR.

Drive-by-Kommentar: @smessmer verschiebt uns zu C++14, an diesem Punkt wird es nicht mehr UB sein. Da dies bald kommt, würde ich mir keine allzu großen Sorgen machen, wenn die UB keine wirklichen Probleme verursacht.

@ezyang : Gut zu wissen. Die meisten Sachen von Drittanbietern wie Eigen nennen immer noch sehr großzügig std::real() .

Bei nicht komplexen Zahlen sind skalar_t und Schub_t vom gleichen Typ. Vielleicht könnte ich den Variablennamen Schub_t durch etwas ersetzen, das freundlicher zu nicht komplexen Zahlen ist, wie z. B. skalar_t_c?

Ich bin mir nicht ganz sicher, aber scalar_t_c scheint etwas weniger klar zu sein als thrust_t (was bedeutet das c überhaupt?) Die fraglichen Typen hier scheinen ziemlich stoßspezifisch zu sein, daher scheint es besser, einen Namen zu verwenden, der direkt über die Absicht spricht.

Ok, ich bleibe bei thrust_t . Wenn jemand in ztype_cuda<>() eintaucht, sollte er sofort herausfinden, dass scalar_t thrust_t für nicht komplexe Typen ist.

Hallo allerseits! Es sieht so aus, als ob gute Fortschritte beim Hinzufügen komplexer Unterstützung für pytorch gemacht werden! Vielen Dank an @dylanbespalko , dass Sie die Initiative ergriffen und auch CUDA-Unterstützung hinzugefügt haben! Auf hoher Ebene möchte ich wissen, wie der aktuelle Fortschritt bei der komplexen Unterstützung ist. Ich interessiere mich hauptsächlich für einen groben Zeitplan für die CUDA-Unterstützung zum Addieren und Multiplizieren komplexer Tensoren (binäre Operationen). Danke!

Hallo @sunilkpai ,

Ich habe eine offene PR, die die binären und unären Operationen auf CUDA unterstützen sollte: #30295.

Ein weiteres Problem ist die Rückwärtsausbreitung. Ich denke, die Ableitung von komplexen abs() ist anders definiert als reelle Zahlen. Ich bin mir nicht sicher, was ich dagegen tun soll, aber Derivate sind in tools/autograd/derivatives.yaml definiert

Ich denke für komplexe Zahlen /dz abs(z) = z/abs(z) . Dies kann auch für reelle Zahlen verwendet werden, ist aber wahrscheinlich langsamer als sgn(z)

@dylanbespalko Vielleicht helfen Ihnen die Tabellen 4.1, 4.2 und 4.3 in meinem Bericht https://arxiv.org/pdf/1701.00392.pdf bei der Definition der Ableitungen.

Für die komplexen Ableitungen (Wirtinger-Kalkül) gibt es zwei Möglichkeiten.
Berechnung der Ableitung nach z oder z konjugiert.
Ich persönlich mag die Ableitung wrt z konjugieren mehr.
Es fühlt sich für Matrixoperationen natürlicher an und die Gradientenaktualisierung benötigt kein Konjugat.
Die Definition von ihnen ist:

  • Ableitung bzgl. z für z = x + jy : dJ/dz = dJ/dx -j dJ/dy
  • Ableitung bzgl. z.conj für z = x + jy : dJ/dz.conj = dJ/dx + j dJ/dy

Aus Ihrem Kommentar gehe ich davon aus, dass Sie im Moment die Ableitung nach z berechnen.
In diesem Fall ist die Ableitung d abs(z) / d z = z.conj / abs(z) . Wenn Sie die andere Definition nehmen, können Sie dem Vorschlag von @Randl folgen.

Lassen Sie mich wissen, wenn ich mehr erklären soll. Ich habe auch einige numpy Implementierungen für die komplexen Ableitungen.

Eine weitere nützliche Operation (insbesondere für Projekte im Bereich der Physik, die Unterstützung für komplexe Zahlen erfordern) ist ein Handler für den exp() -Operator. Im Tensorflow haben wir tf.exp(x + iy) = tf.exp(x) * (tf.cos(y) + 1j * tf.sin(y)) . Ist dies auch in Pytorch einfach zu implementieren?

@sunilkpai , @boeddeker , @Randl ,

Danke für den Bericht über die komplexen Derivate. Ich werde versuchen, dem zu folgen, und ich werde nächste Woche darauf zurückkommen. Ich dachte, ich würde hier einige Links hinzufügen und den Projektstatus beschreiben.

Der Status komplexer Zahlen wird inoffiziell unterstützt und muss über die PyTorch-Erweiterung hinzugefügt werden:

Jede Erweiterung enthält zwei Dinge:

  • Ein .cpp , das alle notwendigen mathematischen Kernel-Registrierungen enthält.
  • Ein test/ -Ordner, der sehr vereinfachte Versionen der Pytorch-Testskripte enthält.
    Sehen Sie in den Testskripten nach, welche Kernel unterstützt werden (und warum andere nicht).

Warum kann ich einen komplexen Tensor nicht auf der Konsole ausgeben?

  • Das Tensor-Python-Objekt hat eine schön gedruckte Formatierung, die einige nicht unterstützte Funktionen aufruft.

    • Sie können den Inhalt von tensor.py ändern, um die Druckformatierung zu umgehen.

    • Oder Sie können Pytorch-Tensoren einfach in Numpy-Arrays konvertieren und dann drucken.

Aktueller Projektstatus:

  • Die CPU-Abdeckung ist ziemlich gut.

    • Die Kernel sind in PyTorch unter 'aten/src/ATen/native/cpu/ </li> <li>Complex number specific code is under 'aten/src/ATen/native/cpu/zmath.h implementiert

    • Die Intel AVX256-Beschleunigung befindet sich unter „aten/src/ATen/cpu/vec256/“.



      • @sunilkpai : Ich kannte die Optimierung von exp nicht. Dies ist der Ordner, in dem Sie das hinzufügen.


      • Lassen Sie mich wissen, ob Sie sich wohl fühlen, die Änderung vorzunehmen.



  • Die GPU-Abdeckung ist auf binäre und unäre Operationen beschränkt:

    • Die Kernel sind in PyTorch unter 'aten/src/ATen/native/cuda/* </li> <li>Complex number specific code is under 'aten/src/ATen/native/cuda/zmath.cuh implementiert

    • Es werden thrust::complex<T> -Datentypen verwendet, die die optimierten Kernel enthalten.

Aktuelle Entwicklung:

  • Warten auf C-basierte TH-Kernel, die in den C++-ATen-Ordner portiert werden.

    • Die Funktion rand() wird benötigt, um die Testfälle zu den internen Tests von Pytorch zu portieren.

    • Einige Indizierungsvorgänge werden derzeit nicht portiert.

    • Derzeit gibt es 168/1300 Mathematikkerne (gegenüber 230 im Oktober), die von TH auf ATen portiert werden müssen.

  • Ich werde versuchen, Unterstützung für komplexe Zahlen hinzuzufügen, sobald diese Kernel in ATen verfügbar sind.

--

FYI. In Bezug auf komplexe Derivate hatten wir eine lange Diskussion in Julia und ihre Implementierung ist jetzt in ChainRules (siehe auch: http://www.juliadiff.org/ChainRules.jl/dev/api.html#ChainRulesCore.Wirtinger ) und Zygote jetzt . Im Allgemeinen brauchen die Menschen nur
\partial L/\partial adjoint(z) als Gradient (per Definition ist es die schnellste Abnahmerichtung), aber die Ableitung ist anders als \partial L/\partial z , eine zusätzliche Schnittstelle sollte hinzugefügt werden, wenn wir eine vollständige Unterstützung für komplexe Zahlen AD wünschen . Für die detaillierten Regeln können Sie überprüfen, was in ChainRules oder Zygote/lib implementiert ist (da es nur allgemeine Regeln gibt, gibt es für die meisten Operatoren keine separaten Regeln für komplexe Zahlen, Rückwärtspass für Dinge wie matmul werden in generischer Definition geschrieben, z. B. adjoint(A) * B )

Warum kann ich einen komplexen Tensor nicht auf der Konsole ausgeben?
Das Tensor-Python-Objekt hat eine schön gedruckte Formatierung, die einige nicht unterstützte Funktionen aufruft.
Sie können den Inhalt von tensor.py ändern, um die Druckformatierung zu umgehen.
Oder Sie können Pytorch-Tensoren einfach in Numpy-Arrays konvertieren und dann drucken.

Ich glaube, ich habe zumindest einen Teil des Drucks in https://github.com/Roger-luo/pytorch-complex zum Debuggen usw. repariert, bin mir nicht sicher, ob dies helfen würde, da sich der Master in der Vergangenheit stark geändert hat Jahr. Sie können es einfach nehmen, wenn es hilfreich ist, ich werde nicht mehr daran arbeiten.

@dylanbespalko Ich bin relativ unerfahren mit den Pytorch-Interna, obwohl ich angefangen habe zu lernen! Ich könnte diese Änderung möglicherweise versuchen, obwohl ich mir aufgrund dessen, was ich in aten/src/ATen/cpu/vec256/* sehe, nicht sicher bin, ob dies notwendig ist, da das Standardverhalten von std::exp(std::complex) genau das ist, was ich erwähnt habe in meinem vorherigen Kommentar: siehe Anmerkungen von https://en.cppreference.com/w/cpp/numeric/complex/exp . Ich bin mir auch nicht sicher, wie sich dies auf die Implementierung dieser Operationen in CUDA übertragen lässt (was derzeit auf real, imag, conj und angle beschränkt zu sein scheint?).

@sunilkpai ,

Ich habe die AVX-Unterstützung für exp() mithilfe der bereitgestellten Gleichung hinzugefügt.

Ich habe auch bemerkt, dass einige Dinge aufgrund einiger kürzlicher Änderungen in PyTorch kaputt waren. Ich habe diese in #30871 behoben.

@dylanbespalko

Gibt es einen Zeitplan für die Portierung von TH zu ATen?
Gibt es eine Möglichkeit, wie ich beitragen kann, da ich mich mit dem Innenleben von Pytorch nicht auskenne?

Ich habe eine Formel für die Backpropagation des Komplexes svd auf dem arxiv gefunden und könnte das implementieren, wenn Sie mir zeigen, wo

Danke für deine Arbeit!

@Jakob-Unfried

https://github.com/pytorch/pytorch/wiki/TH-to-ATen-porting-guide

Die TH-Kernel sind in C implementiert und es besteht wenig Interesse daran, dort komplexe Unterstützung hinzuzufügen, aufgrund all der inhärenten Probleme beim Zählen von Referenzen. Sie können den Fortschritt in aten/src/ATen/native/native_functions.yaml verfolgen, wo jeder Kernel registriert ist:

Suchen Sie nach legacy::cpu::_th und teilen Sie diese Zahl durch 3, um die Anzahl der alten TH-Kernel zu erhalten.
Suchen Sie nach legacy::cpu::_thnn und teilen Sie diese Zahl durch 3, um die Anzahl der alten TH-Neuralnetzwerkkerne zu erhalten.

Jeder Kernel wird normalerweise auf drei verschiedene Arten registriert:
1. Regulärer Kernel y = add(a, b)
2. Inplace-Kernel a = add_(a, b)
3. Kernel ausgeben add_out(a, b, out=y)
Die eigentliche Implementierung befindet sich immer im Output Kernel und die anderen 2 rufen diese Funktion auf.

Die nn-Kernel sind in der Regel einfacher zu portieren, da sie weniger abhängige Kernel haben. Wenn Sie also die Kernel in der umgekehrten Reihenfolge portieren können, in der sie implementiert wurden, dann werden Sie insgesamt weniger Arbeit leisten.

Überprüfung des Portierungsverfolgungsproblems https://github.com/pytorch/pytorch/issues/24507 , auch cc @VitalyFedyunin

Hier ist ein Status-Update zur Unterstützung komplexer Nummern, wie in #32437 angefordert. Ich arbeite heute wieder am CPU-bezogenen Support.

Autograd-Unterstützung

  • Ich hatte nicht viel Zeit dafür.
  • angle() , real() , imag() , conj() wurden alle implementiert.
  • abs() erfordert eine separate Implementierung für komplexe Zahlen. (siehe Anmerkungen von @boeddeker und @Randl oben)

Hardware-Unterstützung

Die Unterstützung komplexer Zahlen ist derzeit out-of-tree implementiert. Hier ist, was das bedeutet:

In-Tree-Code

  • Die mathematischen Operationen werden tatsächlich im Baum implementiert (innerhalb des PyTorch-Quellcodes).
  • Keiner der Pytorch-Tests im Baum validiert die Unterstützung komplexer Zahlen (daher neigen die Dinge dazu, zu brechen).
  • PyTorch migriert von TH zu ATen (#24507).
    - In TH implementierte mathematische Kernel unterstützen keine komplexen Zahlen.
    - Nur in ATen implementierte Kernel können komplexe Zahlen unterstützen.
  • Sie müssen eine PyTorch-Erweiterung installieren, um den komplexen dtype zu aktivieren.

Out-of-Tree-Code

  • Mehrere PyTorch-Erweiterungen sind implementiert und können in Zukunft leicht internalisiert werden:
  • Jede Erweiterung hat vier wichtige Dateien:

    • setup.py: Erstellen und installieren Sie die Pytorch-Erweiterung.

    • [CPU/CUDA/FPGA]ComplexType.cpp: Registrierung des mathematischen Kernels ähnlich CPUType.cpp oder CUDAType.cpp

    • test/test_torch.py: Sehr hässliche Testfälle, die anzeigen, welche Kernel funktionieren, eingeschränkt durch ATen-Unterstützung.

    • test/test_autograd.py: Testen der Autograd-Funktionalität.

Out-of-Tree-PyTorch-Erweiterungen

  1. cpu_strided_complex
    - [x] CopyKernel
    - [ ] TensorFactories (th_random, th_uniform, th_normal)
    - [x] Reichweitenfabriken
    - [x] BinaryOpKernals
    - [x] UnaryOpKernels
    - [x] VergleicheOpKernels
    - [x] PowKernel
    - [x] ReduceOpKernels (th_min, th_max, einige Normen berechnen keine komplexen Konjugierten)
    - [ ] IndexOpKernels (th_masked_select_bool, th_set, th_gather, th_cat)
    - [x] PointwiseOps
    - [x] Lerp-Ops
    - [ ] BlasOps (th_mv, th_mm, th_fmod, th_eig)
    - [ ] LinpackOps (verwendet Blas)
    - [ ] SpectralOps (unterstützt, muss aber bearbeitet werden)

    1. cuda_strided_complex



      • [x] CopyKernel


      • [ ] TensorFactories (siehe CPU-Probleme)


      • [x] BinaryOpKernals


      • [x] UnaryOpKernels (Todo: add angle, real, imag, conj)


      • [ ] CompareOpKernels (Todo)


      • [ ] ReduceOpKernels (Fehlermeldungen bzgl. WARP_SIZE)


      • GPU wird über punktweise Berechnungen hinaus schwierig, jedoch können zusätzliche Funktionen unterstützt werden



  2. vitis_strided_complex

    • Xilinx Vitis ist eine FPGA-High-Level-Syntheseplattform, die Server und eingebettete Geräte unterstützt.

    • Veröffentlicht im Oktober 2019 (wahrscheinlich eingeschränkte Unterstützung für Geräte).

    • Kombiniert SDAccel (Server) mit VIvado HLS (eingebettet).

    • [ ] BinaryOpKernals (Ende Januar)

    • [ ] UnaryOpKernels (Ende Januar)

    • [ ] ReduceOpKernels (Ende Februar).

    • FPGA hat vor kurzem Unterstützung für vektorisierte Objekte hinzugefügt, ähnlich der Vec256-PyTorch-Vorlagenklasse

    • Vec256 war die komplexe Unterstützung, die der CPU hinzugefügt wurde, und es scheint der natürlichere Weg zu sein, $C$- oder $R^N$-Tensorräume zu implementieren

Weitere Updates zu diesem Thema folgen: https://github.com/pytorch/pytorch/issues/33152

Dies mag eine separate Ausgabe verdienen oder auch nicht, aber ich würde es begrüßen zu sehen und denke, dass es derzeit praktisch wichtiger ist, in der Dokumentation etwas zu haben, das erklärt, „wie Pytorch gerade mit komplexen Zahlen arbeitet“. aka kann Addition, Multiplikation, irgendeine Art von Norm, kann keine komplexen Gewichtungen haben usw. All dies kann durch ein paar Zeilen Dokumentation zusammengefasst werden, die erklärt, was das beabsichtigte aktuelle Verhalten auf hoher Ebene ist.

Dies mag eine separate Ausgabe verdienen oder auch nicht, aber ich würde es begrüßen zu sehen und denke, dass es derzeit praktisch wichtiger ist, in der Dokumentation etwas zu haben, das erklärt, „wie Pytorch gerade mit komplexen Zahlen arbeitet“. aka kann Addition, Multiplikation, irgendeine Art von Norm, kann keine komplexen Gewichtungen haben usw. All dies kann durch ein paar Zeilen Dokumentation zusammengefasst werden, die erklärt, was das beabsichtigte aktuelle Verhalten auf hoher Ebene ist.

Hallo @redwrasse, danke für das Feedback! Wir haben derzeit eine Notiz für komplexe Zahlen, die über einige Fackelgrundlagen und komplexe Funktionen spricht, die für komplexe Tensoren auf dem Master unterstützt werden
(von denen die meisten in Version 1.6 enthalten sind) https://pytorch.org/docs/master/complex_numbers.html?highlight=complex. Können Sie uns mitteilen, an welchen anderen Funktionen Sie interessiert sind? Gerne sprechen wir mehr über unseren aktuellen Support und die Pläne für kommende Veröffentlichungen.

Dies mag eine separate Ausgabe verdienen oder auch nicht, aber ich würde es begrüßen zu sehen und denke, dass es derzeit praktisch wichtiger ist, in der Dokumentation etwas zu haben, das erklärt, „wie Pytorch gerade mit komplexen Zahlen arbeitet“. aka kann Addition, Multiplikation, irgendeine Art von Norm, kann keine komplexen Gewichtungen haben usw. All dies kann durch ein paar Zeilen Dokumentation zusammengefasst werden, die erklärt, was das beabsichtigte aktuelle Verhalten auf hoher Ebene ist.

Hallo @redwrasse, danke für das Feedback! Wir haben derzeit eine Notiz für komplexe Zahlen, die über einige Fackelgrundlagen und komplexe Funktionen spricht, die für komplexe Tensoren auf dem Master unterstützt werden
(von denen die meisten in Version 1.6 enthalten sind) https://pytorch.org/docs/master/complex_numbers.html?highlight=complex. Können Sie uns mitteilen, an welchen anderen Funktionen Sie interessiert sind? Gerne sprechen wir mehr über unseren aktuellen Support und die Pläne für kommende Veröffentlichungen.

Danke @anjali411 , es ist toll, diese Dokumentation zu sehen, ich war mir vorher nicht bewusst. Ich denke, was benötigt wird, sind vorne und in der Mitte ein paar Zeilen "aktueller Stand der Unterstützung für komplexe neuronale Netze", aber lassen Sie es mich durchgehen ...

Leute, die an komplexem Autograd interessiert sind, könnten an https://github.com/pytorch/pytorch/issues/41857 interessiert sein, das berührt, welcher Konvention PyTorch folgen wird (JAX oder TF).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen