Pytorch: Интегрирование сложных тензоров

Созданный на 16 февр. 2017  ·  128Комментарии  ·  Источник: pytorch/pytorch

Новое описание от @ezyang :

Работа ведется по адресу https://github.com/Roger-luo/pytorch-complex.

Организационные принципы

  • Поддержка сложных тензоров важна для PyTorch, и мы будем принимать исправления для ядра, которые добавляют небольшое количество кода для добавления сложной поддержки.
  • Добавление сложного включает в себя написание большого количества новых ядер и кода: мы хотели бы, чтобы этот код изначально жил вне репозитория, чтобы людям было проще быстро выполнять итерацию по ним, не проходя основной процесс проверки кода PyTorch. Мы НЕ берем на себя обязательство рассматривать новые большие ядра в краткосрочной перспективе, но в конечном итоге мы хотели бы, чтобы все ядра вернулись в PyTorch.
  • Внешняя библиотека будет создаваться отдельно от PyTorch, поэтому вы сможете поддерживать ее как отдельный репозиторий без необходимости слияния с PyTorch (и решения множества конфликтов слияния).

    • PyTorch может время от времени вносить критические изменения в C++ API; если вы доведете их до нашего сведения, мы сделаем все возможное, чтобы помочь решить эти проблемы.

  • Крючки, необходимые для этого, НЕ будут поставляться с PyTorch 1.0, но они будут поставляться с выпущенной версией PyTorch в недалеком будущем.

Как я буду работать со сложными ядрами?

Вот как будет выглядеть рабочий процесс в устойчивом состоянии.

PyTorch изначально будет содержать API для обращения к сложному dtype, но по умолчанию они ничего не делают. PyTorch определяет torch.complex64 и torch.complex128, ссылаясь на сложные тензоры. Однако, если вы попытаетесь построить тензор таким образом, по умолчанию PyTorch выдаст ошибку:

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

@ezyang предоставил патч, который добавляет эти dtypes в PyTorch. https://github.com/pytorch/pytorch/pull/11173

В среднесрочной перспективе мы объединим поддержку базовой функциональности (например, выделение тензора нулей), чтобы PyTorch изначально поддерживал ее. Разумным прокси для того, что поддержка является «базовой», является встроенная поддержка PyTorch половинных тензоров ЦП (которые крайне бедны).

PyTorch публикует интерфейс для регистрации реализации сложных тензоров. Реализация наследуется от класса TypeDefault (https://github.com/pytorch/pytorch/pull/11013) и переопределяет методы этого класса, чтобы определять реализации функций, для которых у нас есть сложные реализации. Это будет выглядеть примерно так:

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

Этот класс переопределит именно те типы, которые поддерживаются для сложных; все остальные реализации предоставляются TypeDefault и по умолчанию будут вызывать ошибки.

Будет канонический список методов, поддерживаемых в Type (общий интерфейс) в виде автоматически сгенерированного файла, который проверяется в исходном репозитории PyTorch; мы будем сообщать об изменениях API с помощью различий в этом файле. В целом методы находятся во взаимно однозначном соответствии с соответствующими им именами во фронтенде PyTorch.

В общем, когда вы используете операцию, которую еще не реализовали,

ПРЕДУПРЕЖДЕНИЕ. Мы намерены реорганизовать Type в новую систему, которая также поддерживает открытую регистрацию новых операций (это, очевидно, не работает, если у вас есть один суперкласс, определяющий все методы, которые вы, возможно, захотите поддерживать). Таким образом, постарайтесь не слишком привязываться к конкретной стратегии реализации написания Type как подкласса.

Чтобы опубликовать новые сложные операции, вы будете использовать API расширения C++. API расширения C++ задокументирован по адресу https://pytorch.org/tutorials/advanced/cpp_extension.html . По сути, вы можете написать функцию C++, например:

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

Затем API-интерфейс расширения C++ сгенерирует привязку Python, чтобы вы вызывали эту функцию из Python.

Некоторые операции будет «легко» интегрировать в существующий сегодня PyTorch. Например, для реализации бинарных операций, вероятно, имеет смысл расширить add_kernel в BinaryOpsKernel.cpp, чтобы он выполнял диспетчеризацию по сложным типам (и тогда вы получаете его бесплатно, потому что std::complex реализует сложение). Пока эти исправления небольшие и автономные, мы обещаем своевременно объединять их.

ВСЕГДА должна быть возможность разблокировать, просто написав переопределение для Type вместо использования существующей инфраструктуры и выполнив свободное копирование. Но давайте избегать этого, когда это легко!

Автоград. Пока вы работаете над операциями, для которых уже определены производные формулы, вы «автоматически» получите поддержку автоградации, если вы реализуете комплексную поддержку всех составляющих функций, которые вызываются в обратной реализации из производных.yaml. .

В некоторых случаях нам может потребоваться настроить формулы автоградации, чтобы они работали для комплексных чисел; например, градиент «абс» не «град». самостоятельный знак()'. В этих случаях все, что нам нужно сделать, это исправить вышестоящую формулу изменения формулы автоградации «abs» на «abs_backward», которая является функцией, которую можно переопределить.

Для общего комплексного обратного распространения есть несколько ссылок:

  1. Акира «Сложнозначные нейронные сети».
  2. https://giggleliu.github.io/2018/02/01/complex_bp.html

Как правило, нам не нужно изменять автоградацию, поскольку в большинстве случаев мы вычисляем только производные функции с действительным знаком (потери).

План работы

Сегодня многие из необходимых элементов уже готовы, но они не объединены в единое целое. Вот что нужно сделать.

  • [X] Codemod TH, чтобы ifdef не был реальным https://github.com/pytorch/pytorch/pull/11163
  • [X] Встроенная поддержка dtypes torch.complex64 и torch.complex128. https://github.com/pytorch/pytorch/pull/11173
  • [X] Интерфейс для регистрации CPUComplexType и т. д., чтобы эта реализация вызывалась, когда вы запрашиваете сложный тензор с dtype=torch.complex64 или выполняете операцию над сложными тензорами.
  • [X] Земля https://github.com/pytorch/pytorch/pull/11013
  • [X] Сквозной пример, включая работающую систему сборки, отдельно компилируемой программы на C++, которая связывается с libtorch и использует вышеупомянутый интерфейс для реализации сложного тензорного распределения.

Краткосрочный план интеграции. Эти операции «легко» реализовать, поэтому мы должны как можно скорее внедрить их в PyTorch.

  • [X] Базовые тензорные фабрики: torch.empty, torch.zeros, torch.ones
  • [ ] Двоичные операции процессора: add, sub, mul, div #11641
  • [ ] БПФ
  • [ ] ???

Реализация ядра:

TODO: Создайте список на основе https://github.com/Roger-luo/TH/blob/master/ChangeLog.md .

Другие сложные сопутствующие задачи:

  • [ ] Выяснить правила продвижения типов для сложных тензоров и реализовать их в PromotionTypes #11641

Содержание исторического номера

Оригинальный комментарий от @PhilippPelz

Мне было интересно, есть ли интерес к включению сложных тензоров в pytorch.
Для поддержки процессора есть ztorch, и я недавно написал z-cutorch (https://github.com/PhilippPelz/z-cutorch). Это ответвление от cutorch перед рефакторингом для CudaHalfTensor (пока нет аппаратного обеспечения).
Если это не слишком много работы, я хотел бы потихоньку интегрировать его с pytorch. Я использую matplotlib для построения графиков через fb.ptyhon, и каждый раз, когда я переустанавливаю свою систему (собирая все зависимости), получается огромная боль, плюс, похоже, pytorch скоро будет работать под Windows, на которой работает один из моих экспериментальных ПК.
Мне бы тоже понадобились сложные градиенты, так что рано или поздно я бы коснулся и автограда.
В то время как tf поддерживает сложные тензоры как таковые, кажется, что многие операторы еще не поддерживают его (https://github.com/tensorflow/tensorflow/issues/2255), плюс он кажется немного тяжеловатым для моих целей.

Может быть, кто-нибудь мог бы сказать несколько слов, как и с чего начать, если это приветствуется.

feature complex triaged

Самый полезный комментарий

@sunilkpai , @boeddeker , @Randl ,

Спасибо за отчет о комплексных производных. Я постараюсь следовать этому и вернусь к этому на следующей неделе. Я подумал, что добавлю сюда несколько ссылок и опишу статус проекта.

Статус комплексных чисел поддерживается неофициально и должен быть добавлен через расширение PyTorch:

Каждое расширение содержит две вещи:

  • .cpp , который содержит все необходимые регистрации математического ядра.
  • Папка test/ , содержащая очень упрощенные версии тестовых сценариев pytorch.
    Посмотрите в тестовых сценариях, какие ядра поддерживаются (и почему другие не поддерживаются).

Почему я не могу вывести на консоль сложный тензор?

  • Объект Tensor python имеет красивое форматирование, которое вызывает некоторые неподдерживаемые функции.

    • Вы можете изменить содержимое tensor.py , чтобы обойти форматирование печати.

    • Или вы можете просто преобразовать тензоры Pytorch в массивы Numpy, а затем распечатать.

Текущий статус проекта:

  • Покрытие процессора довольно хорошее.

    • Ядра реализованы внутри PyTorch в разделе 'aten/src/ATen/native/cpu/ </li> <li>Complex number specific code is under 'aten/src/ATen/native/cpu/zmath.h

    • Ускорение Intel AVX256 находится в разделе «aten/src/ATen/cpu/vec256/»



      • @sunilkpai : я не знал об оптимизации exp. Это папка, куда вы добавляете это.


      • Дайте мне знать, если вам удобно вносить изменения.



  • Покрытие GPU ограничено бинарными и унарными операциями:

    • Ядра реализованы внутри PyTorch в разделе 'aten/src/ATen/native/cuda/* </li> <li>Complex number specific code is under 'aten/src/ATen/native/cuda/zmath.cuh

    • Используются типы данных thrust::complex<T> , включая оптимизированные ядра.

Текущее развитие:

  • Ожидание переноса ядер TH на основе C в папку C++ ATen.

    • Функция rand() необходима для переноса тестовых случаев на внутренние тесты pytorch.

    • Некоторые операции индексирования в настоящее время не перенесены.

    • В настоящее время имеется 168/1300 математических ядер (по сравнению с 230 в октябре), которые необходимо перенести с TH на ATen.

  • Я постараюсь добавить поддержку комплексных чисел, когда эти ядра станут доступны в ATen.

--

Все 128 Комментарий

Я думаю, нам было бы интересно добавить дополнительную поддержку сложных тензоров. Лучшим способом было бы разветвить и работать с библиотеками C в torch/lib . Это должно быть бесконфликтно с мастером, так что вы можете делать это в течение длительного времени. Как только вы приведете библиотеки в пригодное для использования состояние, вы можете начать писать привязки, и именно здесь мы можем дать некоторые рекомендации о том, как избежать конфликтов в это время.

У меня есть TH с компиляцией сложных типов. Что мне нужно добавить для интеграции с Python?

@PhilippPelz , вы имеете в виду: https://github.com/facebook/ztorch/tree/master/lib/THZ ? или вы создали свой собственный форк TH, который поддерживает сложные типы?

У @killeent есть некоторые заметки о том, как TH связан с Python, он может ими поделиться.

В общем, чтобы получить сложные тензоры, я бы предпочел THZ, так как у него есть тесты и т. Д.

Однако создание бэкэнда CUDA для сложных тензоров — довольно сложная задача, мы даже не начали ее.

Я написал z-cutorch (https://github.com/PhilippPelz/z-cutorch) некоторое время назад. Это ответвление от cutorch перед рефакторингом для CudaHalfTensor (пока нет аппаратного обеспечения).

Это здорово. Я думаю, вы уже приложили большие усилия в этом направлении :)

@soumith Я сделал форк TH со сложными типами. По сути, это THGenerateComplexTypes.h + добавлены процедуры BLAS + LAPACK, остальное почти бесплатно. Мне показалось, что это намного меньше работы, чем проверка того, какие части THZ совместимы, а затем копирование и вставка.

Сейчас я застрял в компиляции THPP, выясняя сообщения компилятора, такие как

/home/philipp/projects/pytorch/torch/lib/tmp_install/include/TH/generic/THBlas.h:6:40: ошибка: ожидается ',' или '...' перед токеном '*'
TH_API void THBlas_(swap)(long n, real *, long incx, real *, long incy);

немного сложно.

Буду признателен за помощь в том, как включить интеграцию с Python. Серверная часть CUDA должна быть в основном копипастом из z-cutorch.

@PhilippPelz вот несколько заметок об обертках PyTorch TH: https://gist.github.com/killeent/4675635b40b61a45cac2f95a285ce3c0

@killeent спасибо, выглядит очень полезно. lib/build_all.sh сейчас компилируется, я думаю, что могу посмотреть каталог csrc.

Теперь это работает:

импортный факел как th
импортировать numpy как np

а = np.массив ([1+1j,2+2j])
б = np.массив ([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()
печать (ath.numpy())

Ушел: [ 4.+4.j 6.+6.j]

наряду с большинством математических функций.
Я добавлю удобные функции и fft в течение следующих недель. Я думаю, должны быть тесты для всего, прежде чем вы сможете объединить это. Если вы знаете кого-то еще, кто интересуется сложными тензорами и готов внести свой вклад в написание тестов, это было бы здорово. На ум приходит эта статья: Deep Complex Networks , возможно, этим ребятам будет интересно.
У меня не будет времени писать все тесты самостоятельно.

@PhilippPelz Спасибо за ваши комментарии. Я проверяю вашу реализацию. И, во-первых, я не уверен в вашей реализации ger . Некоторые сложные функции blas не включены в ваш THBlas.c, например, вы определили GER как zger_ и cger_ в заголовках генерации, но нет функции blas с cger_ в generic/THBlas.c . Хотя я могу использовать ваш gemv и некоторые другие функции. И ИМО, может быть, вам следует добавить .gch в .gitignore? Вы отправили все свои расширения на свою вилку? Сначала я могу сделать запрос на вытягивание вашему мастеру на основе вашей реализации.

И для DOT я думаю, может быть, для сложных векторов более распространены подпрограммы dotc для точки?

И да, если просто использовать real , будет проще реализовать, мне просто было странно, когда real на самом деле сложный...

И что касается тестов, я не видел предыдущих тестов для TH. Куда мне писать эти тесты? или мы просто напишем несколько тестов на Python

Да, извините, я вижу, я, возможно, не втиснул все, что нужно. В понедельник еще раз проверю. Некоторые объявления отсутствуют, например. цгер и цгер

Для DOT использую cdotc и zdotc, вроде их не хватает, обновлю на следующей неделе.

Уточните у сопровождающих pytorch, какие имена они предпочитают на самом деле. Ваш вариант мне больше нравится, просто еще не пробовал.

Да, тесты Python для математических вещей. Должны быть легко изменены для большинства функций, чтобы также включать проверки номеров compelx.

Круто, что ты тоже изучаешь это!

Хорошо, я внес некоторые изменения. Подпрограммы TH blas теперь доступны для сложных

@PhilippPelz Я только что сделал запрос на включение в ваш репозиторий. А для сложных линейных слоев и некоторые другие операторы. может быть много эрмитовых операций (например, bp для сложного линейного слоя). Может быть, добавить какую-нибудь функцию для тензора? Вы проверили часть THNN?

Да, отшельник полезен. cuda fft работает сейчас. cpu fft может быть завернут из numpy. Я еще не коснулся THNN или THCUNN.

@PhilippPelz Я добавил в PR простого отшельника. А не могли бы вы пересмотреть его. Таким образом, мы могли бы увидеть, подходят ли эти изменения, и перейти к следующему шагу. Спасибо! PS. кажется, вы пропустили некоторые заголовки, я также исправляю это и некоторые другие предупреждения. Для сложной функции с реальным выходом должны ли мы возвращать реальный тензор, а не сложный тензор? Я реализовал методы копирования между сложными и реальными типами, так что это возможно.

Я переустановлю все коммиты после вашего обзора.

@PhilippPelz Привет, я совсем запутался в части THPP , которую вы реализовали. Почему у него есть зависимость от воткнутых в Traits.hpp ?. Это вызовет ошибку при компиляции без cuda. Можно ли использовать только какилив Traits.hpp ? Я не понял. Может быть, вы могли бы предложить некоторые подсказки?

@ Роджер-луо Да, у меня также есть некоторые проблемы с этим в другом месте. Сложные типы, которые мы используем, должны быть либо из complex.h, либо из std::complex. Поскольку THPP является оболочкой C++, возможно, std::complex является более подходящим. Не могли бы вы изменить это?

Thrust также вызывает проблемы по той же причине при попытке создать расширения cffi. Прямо сейчас я делаю обходной путь, но правильным способом было бы изменить сложный тип на cuFloatComplex/cuDoubleComplex в THC. чтобы компилятор cffi не жаловался. Я просто хочу продолжить исследование прямо сейчас, это отнимает у меня слишком много времени :( . Если у вас есть время, пожалуйста, сделайте это.

Кроме того, сборка расширения cffi с помощью пользовательских вызовов ядра довольно обременительна, потому что всегда нужно создавать дополнительную библиотеку, скомпилированную с помощью nvcc, которая затем связана с оболочкой cffi. Думаю, другого пути нет. Можно было бы использовать cffi в режиме ABI, но на веб-сайте говорится: «Режим API вместо этого компилирует оболочку CPython C, которая напрямую вызывает целевую функцию. Это сравнительно намного быстрее (и работает лучше, чем libffi когда-либо)».

@PhilippPelz , может быть, reinterpret_cast может быть решением? Я предполагаю, что его следует изменить на cuComplex и использовать reinterpret_cast в THPP. сначала попробую...

Да, я думаю, что нет другого пути, кроме reinterpret_cast, если вы хотите, чтобы THPP собирался также без установки cuda.

@PhilippPelz Я хотел бы помочь. Есть ли где-нибудь список дел?

THNN и THCUNN должны быть включены для сложных типов. Вы можете связаться с @roger-luo? Кроме того, если мы стремимся к интеграции с мастером, модульные тесты должны быть написаны для всех сложных методов.

@elbamos Большая часть работы в THNN будет связана с реализацией новых сложных методов обратного распространения для каждого существующего уровня. В форке Филиппа есть WIP PR. Я перечислил некоторые ссылки.

@apaszke @soumith @PhilippPelz И еще два вопроса:

  • Кто-нибудь знает, почему в THS есть еще один файл $# GenerateXXXTypes.h THS ? Это выглядит так же, как и в TH .

  • Для чего нужен следующий код в 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);
  }
}

Любые предложения по реализации его связанной сложной версии? Я не уверен, что следующая реализация верна...

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

Предыдущий decodeUInt128XE объявляется как

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

В настоящее время я использую std::complex<T> вместо T _Complex в THPP . Я не уверен, что это может быть использовано Python. Или только тип c T _Complex можно использовать для python. Итак, здесь тип dst std::complex<T> .

И если я прав для этой реализации, возможно, нам нужна реализация uint128_t , например https://github.com/calccrypto/uint128_t ? Поскольку кажется, что не все компиляторы поддерживают 128-битное целое число (у gcc есть int128_t и uint128_t).

@PhilippPelz, я заметил, что на вашем форке не включены проблемы - каков статус вашего проекта? я немного расстроен, что сложные тензоры не включены в дорожную карту для pytorch

@el3ment Я добавил сложный бэкенд для процессора https://github.com/pytorch/pytorch/pull/4899 Но он еще не проверен... И я не получил комментариев на свой PR, поэтому я обратился к использованию язык программирования Julia недавно...

В прошлый раз я написал @PhilippPelz по электронной почте, я думаю, его репозиторий все еще находится под версией 0.1, и он занят диссертацией до сентября? И я работал над новым бэкэндом CUDA v0.3, но у меня нет времени, чтобы закончить все эти привязки в одиночку. Функции map/reduce отличаются от v0.1 некоторыми оптимизациями, но их нельзя тривиально преобразовать для поддержки комплексных чисел. Буду рад, если есть желающие помочь...

Я готов помочь.

10 апреля 2018 г. в 22:52 Роджерлуо-уведомления@github.com написал:

@el3ment Я добавил сложный бэкенд для процессора № 4899.

В прошлый раз я написал @PhilippPelz по электронной почте, я думаю, его репозиторий все еще находится под версией 0.1, и он занят диссертацией до сентября? И я работал над новым бэкэндом CUDA v0.3, но у меня нет времени, чтобы закончить все эти привязки в одиночку. Функции map/reduce отличаются от v0.1 некоторыми оптимизациями, но их нельзя тривиально преобразовать для поддержки комплексных чисел. Буду рад, если есть желающие помочь...


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub или отключите ветку.

@elbamos круто, кажется, команда pytorch предпочитает отдельную реализацию. Я обновлю свою вилку позже для других частей позже. Но у меня действительно нет времени на это, и я думаю, мы должны начать работать над этим, когда будет план от команды pytorch, потому что это будет большим расширением для pytorch.

Привет, мой код находится в коммите после версии 0.2.

Я видел, что был довольно большой рефакторинг, который переместил весь тензорный код в Aten. Это означает, что мой форк не может быть легко объединен с текущей версией, и может потребоваться дополнительная работа.

Я все еще пишу свою кандидатскую, но я все равно планировал дождаться 0.4, пока не будет выпущено слияние Variable и Tensor. Я боюсь, что может быть слишком много рефакторинга, чтобы догнать его, если кто-то сделает это раньше.

@elbamos , если вы хотите, вы можете начать добавлять что-то в мою вилку, я объединю ее. На вашем месте я бы просто реализовал то, что вам нужно для любого проекта, который вы делаете. TH(CU)NN — довольно большой интерфейс, и это будет огромная рабочая нагрузка.

@el3ment У меня нет времени заниматься чужими проблемами. Однако я буду объединять материал, если вам нужно реализовать что-то, чего там нет.

Если вам просто нужно что-то, что работает с комплексными числами из коробки, я настоятельно рекомендую tensorflow.

Я также помогу, если возникнут проблемы с компиляцией.

Если я продолжу работу с постдоком, то в какой-то момент перенесу все это в текущую версию. Очень жаль, что facebook не хочет это поддерживать. :((

@PhilippPelz Согласен, это действительно грустно, и на самом деле тензорный поток не поддерживает все операторы в квантовой физике ... Я начал использовать Джулию и отказался от Python.

@Roger-luo Интересно, вы используете определенный пакет julia или это все самописный код?

@PhilippPelz Я разрабатываю в Джулии набор инструментов для квантовых вычислений со многими телами (после того PyTorch PR), он включает в себя сложную/реальную реализацию нейронной сети, основанную на некоторых предыдущих статьях о сложных нейронных сетях, и я обнаружил, что его очень легко разрабатывать с помощью Джулии. метапрограммирование. В настоящее время я просто поместил его в QMTK.jl , он все еще работает, и я еще не закончил все, что хочу. PyTorch меня действительно очень вдохновляет, но очень жаль за сложную поддержку...

Но у меня есть планы разделить его на единый пакет нейронной сети в будущем (просто не хочу поддерживать несколько репозиториев на данный момент). И будет больше людей, присоединяющихся к разработке из Института физики CAS. Я буду принимать PR после его первой помеченной версии (которая будет через несколько недель).

Вы можете посмотреть его, если вам интересно его развитие.

Если у команды PyTorch все еще есть планы на комплексную поддержку в будущем, я готов помочь.

Круто, буду следить!

Привет, ребята, извините, что мы не ответили на этот вопрос с момента его открытия.

Вот два факта:

  1. Мы абсолютно согласны с тем, что PyTorch нуждается в комплексной поддержке, и
  2. У нас нет рабочей силы, чтобы адекватно заполнить длинный хвост, который потребуется для всех сложных операций. (Чтобы убедиться в этом, посмотрите на разреженную поддержку, которая находится у мастера и хромает.)

Поскольку эта проблема была открыта еще в 2017 году, изменилось несколько важных вещей, которые могут сделать реализацию комплексной поддержки немного проще. Во-первых, теперь у нас есть ATen, эргономичная библиотека C++ для работы с тензорами. Это означает, что вам не нужно копировать и вставлять огромные куски кода TH/THC и надеяться, что вы правильно выполнили ручной подсчет ссылок, вы можете писать код на C++, как если бы это был Python, и он будет работать быстро. Во-вторых, мы работаем над новой версией ATen под названием C10, которая намного серьезнее относится к открытым бэкендам, чем ATen (которая является закрытой), что должно упростить работу над сложной поддержкой, поскольку она не Это влечет за собой фактическое разветвление PyTorch, просто добавление нового каталога кода.

Итак, @Roger-luo и @PhilippPelz , мы бы хотели, чтобы вы помогли воплотить в жизнь сложный бэкенд, но нам бы очень хотелось найти способ сделать это, который поможет нам устойчиво поддерживать его в будущем. Поделитесь с нами вашими мыслями.

@ezyang Если вам не хватает рабочей силы, я мог бы попытаться сохранить сложную тензорную часть в будущем, я только что начал свою докторскую диссертацию (и на самом деле это мой год перерыва), и поэтому у меня не будет проблем с написанием диссертации в по крайней мере последние годы. Но я действительно не могу продолжать вносить свой вклад без каких-либо отзывов от команды pytorch. Я думаю, что должна быть дорожная карта для этого большого расширения. И мы могли бы плавно добавить сложную поддержку, чтобы вашим ребятам не пришлось просматривать большой PR, и это облегчило бы усилия разработчиков по отслеживанию основной ветки.

Во-первых, я думаю, что основной проблемой комплексной поддержки будет часть CUDA. Поддерживать процессорную часть с помощью ATen или любых других библиотек довольно просто, я могу переписать процессорную часть всего за несколько дней, если будут какие-либо отзывы. Есть несколько проблем, которые могут меня беспокоить в части CUDA, и я думаю, что это может привести к двум разным подходам:

  1. Используйте float2 и т. д. для имитации одного сложного значения, например, cuComplex в части CUDA.
  2. Используйте существующие FloatTensor и DoubleTensor для имитации сложного тензора в части C++ ATen.

Причина второго подхода заключается в том, что в THC pytorch использует некоторые приемы для ускорения операций сопоставления/уменьшения, и он тривиально не подходит для cuComplex , потому что cuComplex на самом деле float2 , но функции __shfl_xxx изначально не поддерживают float2 . На данный момент я не уверен, как эффективно смоделировать такую ​​функцию за float2 .

Второй подход был бы проще, потому что теперь нам не нужно заботиться об оборудовании, и мы можем значительно упростить работу нашего нового сложного расширения на старых устройствах. Однако это может вызвать некоторые накладные расходы из-за непрерывных адресов памяти.

Кроме того, я обнаружил, что для интеграции комплексных чисел в ATen нам, возможно, придется обрабатывать четыре разных типа, которые на самом деле одинаковы на оборудовании: std::complex , thrust::complex , cuComplex , float2 , что иногда может быть опасно. (на самом деле, я столкнулся с этой проблемой в прошлом году, и reinterpreter_cast было решением).

Хотя я лично предпочел бы писать все более родное.

И я думаю, что нам, вероятно, нужны временные рамки или дорожная карта, и мы можем взять каждую маленькую часть и работать вместе, так что мне не нужно будет самому отслеживать мастера, что совершенно невозможно...

был журнал изменений , когда я пытался внедрить серверную часть ЦП, я классифицировал функции, которые необходимо изменить для комплексных чисел в журнале. Мы могли бы написать дорожную карту на основе этого журнала.

Кроме того, поскольку моя виза была только что отклонена (Австралией), я должен начать учебный год, если вам нужно, чтобы кто-то продолжал работать над этим, я мог бы подать заявку на стажировку.

Я много думал об этом в последний день. Немного грустно, что мы не смогли объединить усилия Роджера как есть, но я подумал про себя

«Как мы можем создать сложную поддержку Tensor, сохраняя при этом низкие накладные расходы на обслуживание?»

Вот что я излагаю как эффективный план достижения вышеуказанной цели:

  • Сложные тензоры не должны быть принципиально новым типом тензоров, как тензоры sparse . Добавление фундаментального типа вызывает много накладных расходов на обслуживание и сквозные изменения. Накладные расходы на обслуживание связаны не с тем, «кто поддерживает сложные биты?», а скорее с тем, что «теперь все разработчики ядра должны знать об этом сложном типе при внесении любых фундаментальных изменений, любых изменений ATen и т. д.».

    • Вместо этого они всегда должны быть [Tensor Shape x 2] или [2 x TensorShape], т. е. Tensor должен иметь одно дополнительное измерение размером 2.

  • Сложные тензоры должны представлять собой небольшой файл/папку из ~2 тыс. строк простого C++, созданного поверх ATen Tensor API.

    • Например, как предлагает https://github.com/pytorch/pytorch/issues/6514 , сложное умножение должно быть реализовано как torch.stack([real1 * real2 - imag1 * imag2, real1 * imag2 + imag1 * real2], dim = -1) , где real1 = input1[:, :, :, ..., 0]

    • Это вредит производительности: да, мы не получим столько производительности, как если бы мы все инлайнили. Однако вопрос: «на сколько?». Я думаю, что мы должны стремиться к снижению производительности на 20% в обмен на здоровую и полнофункциональную + поддерживаемую комплексную поддержку.

    • Наиболее часто используемые сложные функции могут начать получать выделенные ядра, поэтому там, где производительность часто используемой функции снижается более чем на 20%, мы вмешиваемся.

Это должно быть [Tensor Shape x 2], так как BLAS, cublas и MAGMA ожидают свои собственные сложные типы, совместимые по байтам с float2. Также вызовы blas, cublas и magma не могут быть обработаны на уровне python.
Я не думаю, что это будет всего 20% для сложного умножения, разве у вас нет 4 полных операций копирования помимо вычислений для реальной и има-части?
В любом случае, я все равно был бы счастлив, если бы мне не приходилось постоянно вносить изменения из мастера.

Согласитесь с @PhilippPelz , мы можем сильно потерять производительность, так как потеряем комплексную поддержку BLAS, cublas и MAGMA. Но я не уверен в этом. Однако, чтобы быть ясным, сложный тензор полностью отличается от разреженного тензора , большинство библиотек, таких как scipy.sparse , и SparseArrays Джулии рассматривают разреженный массив как композицию фундаментальных многомерных массивов. Но никто не обрабатывает многомерный массив сложного типа, составив два реальных массива... (здесь никто не имеет в виду tensorflow, arrayfire, numpy и Julia). Хотя в MXNet БПФ действительно выполняется с помощью композиции двух реальных тензоров, они не поддерживают сложные... Похоже, что тензорный поток реализовал DataType как оболочку для разных типов сети, включая complex64 и complex128 см. types.proto

О потере производительности

Во-первых, поэлементные функции (вызовы функций map/reduce) не будут иметь большой потери производительности (по крайней мере, память для этих операций будет непрерывной). Но я думаю, что мы должны сначала попытаться протестировать некоторые функции BLAS, чтобы увидеть, имеет ли композиция из FloatTensor аналогичную производительность с Complex64Tensor на графическом процессоре, и сколько мы потеряем в производительности с проект реализации, например:

  • gemm
  • gemv

Составной сложный тензор будет выглядеть примерно так (или просто используйте shared_ptr ):

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

Однако, как я упоминал в недостатках первого подхода, такие функции, как __shfl_xxx , также кажутся препятствием, если мы хотим сделать это более нативным.

в настоящее время torch.fft возвращает один плавающий тензор формы [dim1, ..., dimN, 2]

@ezyang , каковы сроки выпуска C10? Это звучит как очень разумный момент, чтобы начать поддерживать комплекс в главной ветке.

@PhilippPelz Определенно не для 0.4. Мы внутренне ориентируемся на июнь, надеемся, что ждать осталось недолго.

@ezyang , вы упомянули июнь, вам удалось добавить поддержку комплексных чисел в PyTorch?

Думаю, он имел в виду С10, а не комплексную поддержку. C10 упростит добавление сложного. Я так понял.

Да, C10 будет иметь открытую регистрацию как типов Tensor, так и функций. Так что добавить сложный тип в виде отдельного пакета будет намного проще.

Есть ли ETA для комплексных чисел? Означает ли «намного проще» «вероятно, будет сделано быстро»?

@themightyoarfish намного проще, я имею в виду, что мы не будем заблокированы тем, что можно отправить в pytorch master. Мы не установили расчетное время прибытия. Я рассмотрю объем работы, как только мы получим открытую регистрацию в PyTorch.

@soumith , вам все еще нужны люди для работы над этим (сложное число)? Команда PyTorch будет поддерживать комплексные числа? Я могу поработать над этим, если хотите, в сентябре, так как я буду поддерживать QuCumber (он будет активно использовать комплексные числа)

@ Роджер-луо, да. Я хотел связаться с вами, как только у нас будет открытая регистрация в бэкэнде PyTorch, и мы сможем проработать детали.
@ezyang у нас будет открытая регистрация к сентябрю?

@soumith Круто, к вашим услугам.

Мы можем это сделать. (У нас не будет «полной» новой системы, но пока мы настроим ее так, чтобы она поддавалась рефакторингу, мы можем продолжать ее продвигать по мере появления новых разработок. Это будет хорошим тестовым примером для новой открытой системы. регистрация. Я могу убедиться, что это произойдет.)

@ezyang есть какие-нибудь заметки? Я мог прочитать хотя бы это, прежде чем работать над ним. Кажется, многое изменилось с прошлого раза.

@Roger- luo @PhilippPelz Я также хотел бы помочь вам с реализацией сложных тензоров. Мне также это нужно для моих исследований PhD ..

@alexgomezalanis , возможно, у нас мог бы быть канал для обсуждения в slack, я только что создал канал с вызовом #complex-numbers . Но я не начну работать над этим до сентября (еще нужно поработать над частью моего кода на Джулии...)

Кстати, кажется, многое изменилось с прошлого раза. Я использую некоторое время, чтобы наверстать упущенное, прежде чем я получу его в свои руки.

@alexgomezalanis Я не могу. вы должны сначала присоединиться к рабочей области pytorch на слабом уровне. Я не могу найти тебя. Пожалуйста, отправьте электронное письмо по адресу: [email protected] , чтобы получить приглашение.

@Roger- luo @alexgomezalanis Приятно снова увидеть жизнь в сложной проблеме тензора. Я тоже могу предложить поучаствовать, но реально это произойдет не раньше конца сентября/начала октября. Что касается некоторых комментаторов по этому вопросу, поддержка сложных тензоров была бы очень полезна для моего кандидатского проекта.

Я также пытался сохранить свое исследование в прошлом году 😏… но теперь я просто хочу снова вернуть к жизни мой старый код местоположения 1w+. 🤣 давайте общаться в slack!

:) Ага, давай поболтаем в чате. Только что нашел приглашение в почтовой папке.

Незавершенный плагин (только для процессора в краткосрочной перспективе) находится здесь: https://github.com/Roger-luo/pytorch-complex

Пожалуйста, не стесняйтесь дать мне вопрос и PR.

Я разместил заметки о том, как сложная реализация будет выполняться в верхней части этого выпуска.

Недавно я начал использовать PyTorch, и он мне очень нравится — его гораздо приятнее использовать, чем TensorFlow. Тем не менее, поддержка сложных тензоров очень важна для моего исследования (оптические нейронные сети). Над этим еще активно работают? Если да, то кто-нибудь знает (свободные) временные рамки для поддержки сложных тензоров?

Я был бы рад помочь в работе над этим, где я могу, но я относительно новичок в PyTorch, поэтому я еще не имею четкого представления о том, насколько важной является эта функция. Некоторые из моих коллег по лаборатории также выразили большой интерес к поддержке сложных тензоров (в физике добавление этого может сделать Torch практически заменой NumPy с ускорением на GPU) и, возможно, готовы помочь, если это означает получение сложной поддержки в ближайшее будущее.

Привет @bencbartlett

Я все еще пытаюсь работать над этим потихоньку.... но я в настоящее время еще только студент (с довольно нестабильной ситуацией), что означает, что я не могу работать над этим полный рабочий день, а только в свободное время. (Я реализую код, связанный с исследованиями, в Julia с прошлого года, что означает, что только наш устаревший пакет нуждается в лучшей поддержке комплексных чисел от torch.).

Если комплексное число имеет для вас решающее значение и его нужно срочно иметь в запасе, я бы посоветовал попробовать следующее:

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

Это очень медленно... но, по крайней мере, работает. Или у меня была версия C в старом стиле TH.

Это не будет маленьким проектом, который можно сделать за несколько дней. Поэтому я не могу гарантировать какие-либо конкретные сроки полной функциональной поддержки с комплексным значением на CPU или CUDA.

Однако я хотел бы помочь вам работать вместе со мной над этим. Я бы посоветовал вам начать с решения проблем, которые я разместил в репозитории расширений. И, пожалуйста, не стесняйтесь спрашивать меня через Slack, по электронной почте или по проблеме, если у вас есть вопросы (поскольку документации пока не так много).

К сожалению, у меня пока нет доступа к PyTorch Slack. (Я дважды писал по электронной почте с просьбой о приглашении, но не получил ответа.) Может ли кто-нибудь пригласить меня? (бенбартлетт@stanford.edu)

@Roger-luo Я обязательно посмотрю вашу вилку, но не могу обещать, что сильно помогу - мой C++ заржавел, и, как вы указали, трудно найти время, чтобы поработать над этим как над ученик. Утилиты QuCumber хороши, но, к сожалению, они не будут мне особенно полезны: пока сложные тензоры не будут поддерживаться графическим процессором или не будут поддерживаться autograd и torch.nn, они не предоставляют много полезного, кроме того, что может предложить NumPy.

@soumith @ezyang Было бы здорово привлечь к этому больше внимания со стороны команды PyTorch! Комплексная поддержка кажется важной функцией для общей тензорной библиотеки, она практически необходима в физике, и особенно в ML за последние несколько лет наблюдается быстро растущий интерес к моделям с комплексными значениями.

Подход @bencbartlett QuCumber можно использовать на графическом процессоре с AD ... он просто очень медленный ... Я имею в виду, что если вам просто нужен этот AD, вы можете его использовать.

Да, честно говоря, я использую немного модифицированную версию https://github.com/FluxML/Flux.jl и какой-то свой собственный пакет в Джулии для исследований (мне также нужен сложный AD на GPU с тензорами в некоторых ситуациях ). Пакет source2source AD ​​Zygote.jl может выполнять AD на сложных тензорах, но он находится на очень ранней стадии, что может привести к ошибкам сегмента. Экосистема еще не настолько стабильна по сравнению с факелом, мне иногда приходится немного хакнуть эту реализацию для самостоятельного использования... Но в основном она работает для того, что мне нужно для исследований в области квантовой физики. У меня также могут быть сложные тензоры на GPU.

Я не думаю, что поддержка сложных значений для torch.nn необходима, нам может понадобиться добавить несколько определений для autograd после того, как сложный тензор станет функциональным, потому что такие вещи, как линейные слои, могут оставаться прежними. . И некоторые функции активации могут не иметь стандартного расширения в гильбертовом пространстве... (Вы можете проверить сообщение в блоге моего соавтора @GiggleLiu )

Что касается расширения pytorch-complex, я не уверен, когда мы сможем получить полную поддержку AD на GPU... мне это все еще кажется довольно далеким. Я бы сказал, что реализация ЦП пройдет через некоторый период, который потребует исправлений в основном дереве (например, продвижение типов, поддержка simd и т. д.), это также может быть связано с грядущей реализацией ATen на C++ и избавлением от TH и т. д. и тогда мы сможем быстрее добавлять операторы для сложных тензоров.

Я могу подать заявку на стажировку весной (о чем я только что спросил @ezyang ). Так что я мог бы работать над этим полный рабочий день в течение нескольких месяцев, прежде чем я начну свою докторскую диссертацию. Давайте посмотрим.

Тем временем я реализовал свою версию сложного умножения. Однако, когда я его профилирую, оказывается, что значительное количество времени уходит на: torch._C_._cuda_isDriverSufficient

image

У вас есть идеи, почему? Если вы знаете лучшую реализацию сложного умножения, сообщите мне об этом. Почему-то моя версия (хотя и оптимизирована для количества умножений: 3 вместо 4) кажется относительно медленной, например, irfft тензора out в 10 раз быстрее, чем мое поэлементное умножение. Поддерживается ли сложное умножение на уровне С++ PyTorch?

def complex_mul(x, y, out):
    uavc = x[..., 0] * (y[..., 0] + y[..., 1])
    out[..., 0] = uavc - (x[..., 0] + x[..., 1]) * y[..., 1]
    out[..., 1] = (x[..., 1] - x[..., 0]) * y[..., 0] + uavc
def test_complex_mul_out_tensor(self):
        N, C, H, W, I = 128, 3, 32, 32, 2
        K = 16  # number of filter banks
        repetitions = 1000
        dtype = torch.float
        if torch.cuda.is_available():
            device = torch.device("cuda")
        else:
            device = torch.device("cpu")
        x = torch.randn(N, 1, C, H, W, I, dtype=dtype, device=device)
        y = torch.randn(K, C, H, W, I, dtype=dtype, device=device)
        start_mul_time = time.time()
        out = torch.empty(N, K, C, H, W, I, dtype=dtype, device=device)
        for _ in range(repetitions):
            complex_mul(x, y, out)
        print("multiplication time: ", time.time() - start_mul_time)

Мы пытаемся поддерживать его с C++. смотри пост вверху. Если вы можете скомпилировать расширение, оно должно работать для скалярного умножения, по крайней мере, на данный момент....

Ваша реализация похожа на то, что мы имеем в QuCumber. Это может вызвать много дополнительных потоков графического процессора, если вы не вызовете правильное ядро ​​cuda для комплексного числа. И вы можете потерять SIMD, если у вас нет бэкэнда C++ в качестве поддержки в Python.

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

@Roger- luo @apaszke @soumith Спасибо за эту тему, кстати. Я реализовал базовый сложный тензор, собранный из подкласса torch.Tensor.

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

Я проверил Tensorflow и numpy. Градиенты и все операции, которые я реализовал, соответствуют их результатам!

Это просто задумано как пережиток, пока PT полностью не поддерживает сложные тензоры.

Функции:

  1. Реализованы тесты.
  2. Поддерживается Pypi (т.е. установка pip)
pip install pytorch-complex-tensor

https://github.com/williamFalcon/pytorch-комплекс-тензор

Спасибо @williamfalcon !

Любое обновление? Просто интересно, будет ли план по интеграции поддержки сложных типов в pytorch.

Привет, @whmrtm

@ezyang работает над https://github.com/Roger-luo/pytorch-complex/issues/4 . Или любой, кто заинтересован в этом, может помочь нам запустить его. Эта проблема решит некоторые основные проблемы с трансляцией (после того, как эта проблема будет решена, вы сможете использовать множество функций). Пожалуйста, не стесняйтесь сделать любой пиар или попросить меня добавить вас в качестве соавтора.

Я не смогу работать над чем-либо до лета, нужно закончить свежий релиз для нашего собственного пакета.

Привет, @whmrtm

@ezyang работает над Roger-luo/pytorch-complex#4 . Или любой, кто этим интересуется, может помочь нам запустить его. Эта проблема решит некоторые основные проблемы с трансляцией (после того, как эта проблема будет решена, вы сможете использовать множество функций). Пожалуйста, не стесняйтесь сделать любой пиар или попросить меня добавить вас в качестве соавтора.

Я не смогу работать над чем-либо до лета, нужно закончить свежий релиз для нашего собственного пакета.

Спасибо за обновление, я посмотрю, что я могу сделать.

Привет @Roger-луо

Могу ли я получить доступ к слабому каналу, связанному с темой поддержки сложных тензоров ([email protected])? Я отправил письмо за приглашением, но пока ничего не произошло. Прямо сейчас я пытаюсь выяснить точки, где начать способствовать этому вопросу. Я предполагаю, что https://github.com/Roger-luo/pytorch-complex/issues/4 сейчас является текущей точкой входа?

@beconstant да, это отправная точка, это должно заставить работать некоторые функции вещания, но я не знаю, почему он выдает ошибку продвижения типа на cuda, он работал на процессоре. (Хотя мы не собираемся поддерживать cuda в первую очередь, это приведет к сбою сборки)

Я не могу отправить вам письмо с приглашением (у меня нет доступа). Я думаю, вы должны следовать официальному руководству pytorch, чтобы присоединиться к slack. Но всегда можно обсудить в теме/PR.

@ Роджер-луо, хорошо, понял :)

Дайте мне знать, если вам, ребята, нужна помощь. Я начну со сборки указанной версии pytorch. Есть ли прогресс в pytorch-complex/issues/4 ?

Дайте мне знать, если вам, ребята, нужна помощь. Я начну со сборки указанной версии pytorch. Есть ли прогресс в pytorch-complex/issues/4 ?

@dylanbespalko Привет, мне срочно нужен pytorch, реализованный в версии с комплексным значением.
Большое спасибо за ваш вклад.

С наилучшими пожеланиями,
Целлар209

Привет @ Zellar209 ,

У меня такое ощущение, что @ezyang усердно работает над одной из самых больших проблем ( pytorch-complex/issues/4 ). Сейчас у меня есть система AMD и система Nvidia через 3 недели, которую я могу использовать для увеличения поддержки графического процессора.

Я предполагаю, что проблема заключается только в том, что изменение продвижения исходного типа ломает CUDA, пока этот PR решен, по крайней мере, некоторые операторы работают на процессоре, у нас пока нет поддержки CUDA...

ИМХО, я думаю, что мы должны сначала сосредоточиться на процессоре и заставить все работать, а затем уже думать о GPU.

Поддержка только процессора в порядке. Является ли проблема продвижения этого типа ( pytorch-complex/issues/4 обрабатывается внутри fb? Можно ли работать над этим извне?

Привет @dylanbespalko; Я сказал @Roger-luo, что собираюсь разобраться с этим (потому что я, вероятно, лучше всего могу понять, в чем проблема), но у меня еще не было времени на это посмотреть. Если вы хотите узнать, как решить проблему, я буду рад посоветовать.

Привет @ Zellar209 ,

У меня такое ощущение, что @ezyang усердно работает над одной из самых больших проблем ( pytorch-complex/issues/4 ). Сейчас у меня есть система AMD и система Nvidia через 3 недели, которую я могу использовать для увеличения поддержки графического процессора.

Да, мне сейчас не нужен GPU, я использую систему MAC. Но у меня были некоторые ошибки при создании этого проекта.

Привет @ Zellar209 , не могли бы вы опубликовать, что вы получили в выпуске pytorch-complex? Я думаю, что что-то не так с новым Xcode для Mac, что затрудняет его сборку. Но людям понадобится еще несколько сообщений об ошибках, чтобы понять, почему.

Я спросил об ОС и сообщении об ошибке, но вы не ответили...

Привет @dylanbespalko; Я сказал @Roger-luo, что собираюсь разобраться с этим (потому что я, вероятно, лучше всего могу понять, в чем проблема), но у меня еще не было времени на это посмотреть. Если вы хотите узнать, как решить проблему, я буду рад посоветовать.

Спасибо за ранний ответ.

1. Когда я запускаю «python setup.py install» с помощью gcc (по умолчанию), я получаю такие ошибки:

создание расширения 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: ошибка: нераспознанный параметр командной строки '-stdlib=libc++'

ошибка: команда 'gcc' не удалась со статусом выхода 1

2. Когда я использую clang для его компиляции, возникают следующие ошибки:

В файле, включенном из src/module. ЦПП: 2 :
В файле из src/CPUComplexType.h:60:
src/CPUComplexTypeImpl.h:102:105: предупреждение: «IntList» устарел [-Wdeprecated-declarations]
Tensor & CPUComplexType::set_(Tensor & self, Storage source, int64_t storage_offset, размеры IntList, шаги IntList) const {
^
/anaconda3/lib/python3.6/site-packages/torch/include/c10/util/ArrayRef.h:273:7: примечание: «IntList» здесь явно помечен как устаревший
используя IntList C10_DEPRECATED_USING = ArrayRef;
^
В файле, включенном из src/module. ЦПП: 2 :
В файле из src/CPUComplexType.h:60:
src/CPUComplexTypeImpl.h:105:76: ошибка: нет члена с именем 'scalarTypeToDataType' в пространстве имен 'at'
auto source_ = checked_storage(источник,"источник",2, DeviceType::CPU, at::scalarTypeToDataType(CPUComplexTypeInfo::scalar_type));
~~~~^
Сгенерировано 7 предупреждений и 2 ошибки.

ошибка: команда 'clang' не удалась со статусом выхода 1

Я не могу это исправить. Я очень надеюсь, что вы можете мне помочь!

Привет ребят,

Спасибо за ваш отзыв. Я думаю, что могу потратить неделю на изучение этого. До сих пор я скомпилировал pytorch-complex @Roger-luo следующим образом:

@Zellar209 Zellar209 : я прикрепил свои переменные среды, работающие в macOS 10.13.

  1. Удалите существующий дистрибутив pytorch следующим образом.
    conda удалить pytorch
    пип удалить факел
    pip uninstall torch # выполнить эту команду дважды
    python setup.py чистый
    Удалите папку torch в папке python site-packages, если она существует.
    Переименуйте (или удалите) предыдущую исходную папку pytorch (что-то имело в виду).

  2. Установите версию PyTorch 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. Установить pytorch-комплекс
    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. Создайте сложный тензор
   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:

Все для продвижения типов для тензорных операций вроде бы сделано в c10/core/ScalarType.h
Я нашел ошибку AT_ERROR("promoteTypes with complex numbers is not handled yet; figure out what the correct rules should be”);
Похоже, мне нужно добавить запись для c8 и c16 в эту таблицу.
Это как-то связано с 9515 ? Я думаю, что это просто для вызова функций numpy.
Это хорошее место для начала?

9515 не имеет отношения. Тем не менее, исправление этого кода в ScalarType.h — хорошее место для начала.

Я исправил код в ScalarType.h
BinaryOps (add, sub, mul, div) работает, но только если оба аргумента являются тензорами.
Некоторые другие странные проблемы, но мне нужно взглянуть на это еще немного.

@dylanbespalko Я добавил рекламные акции здесь: https://github.com/pytorch/pytorch/pull/11641

Вы можете просто скопировать это, но проблема в том, что это каким-то образом ломает CUDA.

IIRC, была ошибка проводки из-за версии gcc. У меня были некоторые обходные пути.

А, спасибо @Roger-luo. Я смотрел комментарии #11641 . Завтра я лучше скопирую код.

Как узнать, что я сломал CUDA, если у меня нет устройства CUDA? Я предполагаю, что CI скажет мне?

Да, пока вы отправляете PR, он скажет вам, какой из них сломан. И если все просто пройдет, тогда мы могли бы просто объединить это и заставить все работать.

Хорошо, тогда я начну отправлять PR, чтобы знать, когда это произойдет.

@dylanbespalko Привет, в вашей среде все еще есть ошибки?
Если вы исправите это, пожалуйста, поделитесь с нами. Большое спасибо.

Привет ребят,

Я попытался сделать несколько PR после копирования нескольких коммитов @Roger-luo. К сожалению, сейчас у меня нет графического процессора CUDA, а машины CI с CUDA не инициализируются. Я не могу воссоздать сбой теста CUDA прямо сейчас, поэтому я вернусь к этому через несколько недель, когда смогу запустить его локально на этом графическом процессоре. По крайней мере, выглядит многообещающе.

@ezyang , @Роджер-луо

Я взглянул на PR Роджера № 11641 :

  • Он собирается и работает на моей машине с CUDA 9.0.
  • Не удается выполнить сборку на машинах CI, на которых работает CUDA 9.0.

Я также взглянул на некоторые из последних разработок PyTorch:

  • Презентация от @ezyang, описывающая, как написать расширение C++/CUDA, которое может определять пользовательское устройство/макет/dtype .

    • Более свежий PR № 21964 , который «удаляет ComplexHooksInterface», но определяет расширение C++ для сложных чисел, расположенное по адресу pytorch/test/cpp_extensions/complex_registration_extension.cpp.

Мне кажется, что разрабатывается новая возможность расширения «вне дерева», которая позволит мне исследовать поддержку комплексных чисел, не нарушая остальную часть pytorch. Моя цель:

  1. Определить поддержку сложных процессоров без AVX.
  2. Определить сложную поддержку CUDA с помощью Thrust.

@ezyang
Можете ли вы указать ожидаемые сроки для этого внедеревянного расширения устройства / макета / dtype , которое вы представили? Можем ли мы ожидать эту функцию в ближайшие 3 месяца?

@ezyang

Можете ли вы объединить поддержку комплексных чисел на ЦП без поддержки AVX/SSE? Я планирую представить в отдельных мерж-реквестах следующее:

  • [ ] Добавлена ​​комплексная поддержка ядер CPU BinaryOp.
  • [ ] Добавлена ​​комплексная поддержка CPU TensorFactories.
  • [ ] Добавлена ​​комплексная поддержка CPU FillKernels
  • [ ] Добавлена ​​комплексная поддержка ядер CPU Range.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU Unary.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU Compare.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU TensorCompare.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU ReduceOp.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU PointwiseOps.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU learpOps.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU LinearAlgebraOps.
  • [ ] Добавлена ​​комплексная поддержка ядер CPU SpectralOps.

Я планирую протестировать это на процессорах Intel/ARM в ближайшие пару дней.

@ezyang ,

Я изучаю такие операции, как fft() и var() , где реализация комплексного числа должна преобразовывать тензорные данные в двойной тензор формы: (complex_shape, 2) . Это не работает ни с какими существующими тензорными методами:

  1. 'tensor.to(torch.float64): сохраняет только реальную часть и возвращает тензор той же формы.
  2. 'tensor.view(new_shape): новая форма должна иметь такое же количество элементов.

Очевидно, я могу сделать что-то неэффективное, например:

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]

Очевидно, что это создание копий, когда все, что мне нужно, это static_cast<double> и изменить форму тензора на (old_shape, 2) . Есть ли у вас какие-либо предложения о том, как это сделать?

Кроме того, в numpy есть хак, который позволяет вам это сделать:

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

Возможность установить dtype действительно работает в этой ситуации, однако это может быть непредсказуемо.

Некоторая дополнительная информация об интерпретации комплексного числа как массива действительных чисел длины 2. Следующее допустимо в C++11.

Для любого указателя на элемент массива комплексных чисел p и любого допустимого индекса массива i, reinterpret_cast(p)[2 i] — действительная часть комплексного числа p[i], а reinterpret_cast(р)[2 i + 1] — мнимая часть комплексного числа p[i]. (Начиная с С++ 11)

Я думаю, это означает, что можно преобразовать complex_tensor в real_tensor с формой (complex_shape, 2), а затем выполнить операцию без вызова real() и imag() , которые выделили новую память.

@dylanbespalko Я боялся, когда вы спросите об этом :) Гарантия std::complex означает, что если у вас есть указатель данных std::complex<float>* , вы можете безопасно преобразовать его в float* (бормочет строгое псевдоним), а затем передайте его тому, что вы используете. Если вам нужно только реализовать fft/var, где вы можете передать эту низкоуровневую репутацию, это будет проще всего.

Однако, если вам нужно буквально пересмотреть сложный тензор как тензор с плавающей запятой, мы немного запутались, потому что сегодня в PyTorch нет прецедента для этого. Тип хранилища всегда согласовывался с типом тензора. Поэтому, если вы создаете сложное хранилище, вы не сможете рассматривать его как хранилище с плавающей запятой.

У меня была одна мысль: может быть, нам следует ослабить этот инвариант. Идея такова:

  1. Мы всегда выделяем хранилища как рассматриваемый «невекторизованный» тип. Так что для комплексамы выделяем плавающий тензор.
  2. Tensor dtype может не совпадать с dtype хранилища, но только как векторизованный вариант базового типа.

Я не уверен, сколько кода нам нужно изменить, чтобы этот инвариант появился.

@ezyang ,

Да, это было неизбежно...

Если вам нужно только реализовать fft/var, где вы можете передать эту низкоуровневую репутацию, это будет проще всего.

Да, это возможно во многих случаях. Можете ли вы предоставить фрагмент кода, как интерпретировать тензорные данные как std::vector?

Однако, если вам нужно буквально пересмотреть сложный тензор как тензор с плавающей запятой,....

Я бы предположил, что редко можно увидеть тензор с использованием другого dtype. Я реализовал метод set_dtype() для Tensor , но получил несколько ошибок. Я также не обновлял шаги, чтобы отразить изменения в форме. Я не уверен, почему настройка dtype работает в numpy (это совпадение?), Однако, когда вы загружаете данные в цифро-аналоговый преобразователь (DAC), он часто ожидает, что реальные/мнимые данные будут чередоваться. Возможно, это мотивирует необходимость отделить тензорный dtype от dtype хранилища, как вы предложили.

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

Да, это возможно во многих случаях. Можете ли вы предоставить фрагмент кода, как интерпретировать тензорные данные как std::vector?

Не совсем std::vector, но я представляю что-то вроде этого:

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;

Я реализовал метод set_dtype() для Tensor, но получил несколько ошибок. Я также не обновлял шаги, чтобы отразить изменения в форме.

Да, это, вероятно, плохая идея, если вы не исправите шаги. Также я не большой поклонник преобразования тензоров в другие dtypes; лучше просто сделать это не на своем месте :)

однако, когда вы загружаете данные в цифро-аналоговый преобразователь (ЦАП), он часто ожидает чередования реальных и мнимых данных. Возможно, это мотивирует необходимость отделить тензорный dtype от dtype хранилища, как вы предложили.

Да, в конечном счете, это правильно, но я согласен, что сейчас проще этого не делать.

@ezyang ,

Я начинаю возиться с поддержкой сложных чисел CUDA.

Есть два бинарных совместимых варианта:

  1. cuComplex : Очень простая поддержка добавления, подпрограммы, мультипликации, div, реальной поддержки изображений.
  2. Thrust::complex : замена std::complex , которая поддерживает выделение памяти хоста и устройства.

Кажется, что контейнер Thrust::complex — это то, что нужно. Thrust::Complex API предполагает, что контейнеры thrust::complex<T> могут быть размещены в памяти хоста и устройства, а контейнеры std::complex<T> могут быть размещены только в памяти хоста:

__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. Означает ли это, что AT_DISPATCH_COMPLEX_TYPES должен установить using scalar_t = thrust::complex<double> вместо using scalar_t = std::complex<double> ?

  2. Как Pytorch автоматически вызывает эквиваленты CUDA std::log для реальных типов данных? Откуда я знаю, что существует CUDA-эквивалент математического ядра?

  1. Я думаю, что сложность универсального использования thrust::complex<double> для ЦП и CUDA заключается в том, что мы фактически не строим против тяги, если вы делаете сборку только для ЦП. Я думаю, есть куча вариантов; мы могли бы свернуть наш собственный сложный тип (аналогично тому, как мы сворачиваем свой собственный половинный тип), или вы могли бы просто переинтерпретировать приведение к победе, потому что std::complex<> определяется как имеющее определенный двоичный макет. Это зависит от вас, но сейчас кажется проще просто переосмыслить приведение типов.
  2. У нас есть математические перегрузки в THCNumerics.cuh, это ответ на ваш вопрос?

@iotamudelta поднял вопрос о соответствии C++11 в #29547.

std::real — это только constexpr из C++14

Если я правильно понимаю, std::real() должен быть constexpr , чтобы компилятор hcc мог скомпилировать инструкцию для __device__ .

Возможные решения:

  1. Найдите другой метод или функцию для преобразования complex<double> в double :
  1. Найдите способ обернуть функцию:

    • Большинство вызовов std::real выполняются в aten/src/ATen/native/cpu/zmath.h . Пример: замените inline constexpr :

      inline VALUE_TYPE real_impl (SCALAR_TYPE z) ->
      constexpr VALUE_TYPE real_impl (SCALAR_TYPE z)

      inline std::complex<float> real_impl <std::complex<float>> (std::complex<float> z) -> constexpr std::complex<float> real_impl <std::complex<float>> (std::complex<float> z)

      inline std::complex<float> real_impl <std::complex<double>> (std::complex<float> z) -> constexpr std::complex<float> real_impl <std::complex<double>> (std::complex<float> z)

Это не будет компилироваться, потому что все еще есть вложенный вызов std::real() , который не является constexpr .

3. Если я использую std::complex::real() вместо std::real() это похоже на совместимость с С++ 11.

  1. Я думаю, вы говорите, что независимо от того, что я делаю, этот код будет UB до C++14. Есть ли другой способ конвертировать std::complex<double> в double , отвечающий вашим требованиям?

@iotamudelta , @bddppq , @ezyang ,

Я добавил поддержку сложных UnaryOps и BinaryOps в CUDA Throw::complex API, но мне нужно задать несколько вопросов, прежде чем отправить его.

Я определил шаблонную функцию, которая позволяет вам использовать типы данных Thrust::Complex при работе с комплексными числами.
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

Затем в aten/src/ATen/native/cuda/BinaryOpsKernel.cu
Заменять:

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

С участием:

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

Вопросы

  1. @ezyang : для некомплексных чисел scalar_t и Thrust_t имеют один и тот же тип. Может быть, я мог бы заменить имя переменной thrust_t на что-то более удобное для несложных чисел, например, scalar_t_c ?
  2. Библиотека тяги, кажется, широко упоминается в коде:
    a) @bddppq : есть ли причина, по которой я должен использовать cuComplex вместо thrust::complex ?
    б) @iotamudelta : в ROCm2.7 убрана тяга бедрами. Должен ли я вместо этого использовать hip_complex ?
    Thrust::complex поддерживает больше функций, чем cuComplex .

Пожалуйста, дайте мне знать, что вы думаете.

@iotamudelta

Я обновил обсуждение std::real(). Можете ли вы подтвердить, что std::complex::real() решит проблему.

Привет @dylanbespalko ,

Я предполагаю, что @iotamudelta жалуется на то, что cast_and_store для сложных типов отсутствует C10_HOST_DEVICE , это будет UB, если этот путь кода когда-либо будет выполняться на графическом процессоре.

В настоящее время эта утилита динамического приведения используется только в GPU TensorIterator и только при повышении типа. По той причине, что в настоящее время комплекс не поддерживается на графическом процессоре, cast_and_store для сложных типов прямо сейчас не имеет квалификатора C10_HOST_DEVICE и использует std::real , что совершенно нормально для хоста. только функция. Здесь нет УБ, потому что он не используется, и вам не о чем беспокоиться.

Но так как вы хотите добавить поддержку сложного в GPU, а сложное поддерживается продвижением типа, как мы видим в https://github.com/pytorch/pytorch/blob/master/c10/core/ScalarType.h#L398 - L420, вам нужно быть очень осторожным с этим кодом, и есть несколько модификаций, которые вам могут понадобиться, чтобы заставить его работать:

Конечно, вам нужно добавить C10_HOST_DEVICE , как это делает @iotamudelta в https://github.com/pytorch/pytorch/pull/29547 , но этого недостаточно, потому что просто добавить C10_HOST_DEVICE без других изменений по-прежнему UB на С++ 11, как упоминалось @iotamudelta , хорошим решением может быть то, что вы упомянули: используйте std::complex::real() для замены std::real .

Но помимо этого, если вы посмотрите на файл https://github.com/pytorch/pytorch/blob/master/c10/util/TypeCast.h , вы увидите внутри fetch_and_cast что-то вроде:

#ifndef C10_HOST_DEVICE
    AT_FORALL_COMPLEX_TYPES(FETCH_AND_CAST_COMPLEX_CASE)
#endif

Этот путь кода отключен на графическом процессоре. Вам нужно включить его и заставить его работать.

Кроме того, я не видел преобразования между complex<float> и complex<double> внутри fetch_and_cast и cast_and_store . Возможно, вам также потребуется добавить преобразование для этого. Убедитесь, что вы тщательно протестировали охват этих функций всех dtypes.

Копия: @ezyang и @bddppq

Также @dylanbespalko , пожалуйста, скопируйте меня, если вы вносите какие-либо изменения в TypeCast.h в своем PR.

Хорошо, мне нужно исправить пару мелких вещей с torch.real() и torch.imag() на ARM, так что я исправлю TypeCast.h и некоторые другие, пока я этим занимаюсь. Я скопирую вас, ребята, в PR.

Управляйте комментариями: @smessmer переводит нас на C++14, после чего это не будет UB. Поскольку это произойдет в ближайшее время, если UB не вызывает реальных проблем, я бы не стал слишком беспокоиться об этом.

@ezyang : Приятно знать. Большинство сторонних вещей, таких как Eigen, по-прежнему очень либерально называют std::real() .

Для некомплексных чисел scalar_t и Thrust_t имеют один и тот же тип. Может быть, я мог бы заменить имя переменной Thrust_t на что-то более удобное для несложных чисел, например scalar_t_c?

Я не совсем уверен, но scalar_t_c кажется немного менее ясным, чем thrust_t (что вообще означает c ?). так что кажется лучше использовать имя, которое прямо говорит о намерении.

Хорошо, я буду придерживаться thrust_t . Если кто-то погрузится в ztype_cuda<>() , он должен сразу понять, что scalar_t — это thrust_t для несложных типов.

Всем привет! Похоже, что достигнут значительный прогресс в добавлении комплексной поддержки в pytorch! Спасибо @dylanbespalko за инициативу и добавление поддержки CUDA! С высокого уровня мне интересно узнать, каков текущий прогресс в комплексной поддержке? Меня больше всего интересуют приблизительные сроки поддержки CUDA для сложения и умножения сложных тензоров (бинарных операций). Спасибо!

Привет @sunilkpai ,

У меня есть открытый PR, который должен поддерживать бинарные и унарные операции в CUDA: #30295.

Еще одна проблема связана с обратным распространением. Я думаю, что производная комплексного abs() определяется иначе, чем действительные числа. Не уверен, что с этим делать, но производные определены в tools/autograd/derivatives.yaml

Я думаю, что для комплексных чисел /dz abs(z) = z/abs(z) . Это можно использовать и для действительных чисел, но, скорее всего, это будет медленнее, чем sgn(z)

@dylanbespalko Возможно, таблицы 4.1, 4.2 и 4.3 в моем отчете https://arxiv.org/pdf/1701.00392.pdf помогут вам определить производные.

Для сложных производных (исчисление Виртингера) есть два варианта.
Вычисление производной по z или сопряженной по z.
Лично мне больше нравится сопряжение производной по z.
Это кажется более естественным для матричных операций, а обновление градиента не требует сопряжения.
Их определение:

  • производная z для z = x + jy : dJ/dz = dJ/dx -j dJ/dy
  • производная z.conj для z = x + jy : dJ/dz.conj = dJ/dx + j dJ/dy

Из вашего комментария я предполагаю, что вы вычисляете производную относительно z на данный момент.
В этом случае производная равна d abs(z) / d z = z.conj / abs(z) . Когда вы принимаете другое определение, вы можете следовать предложению @Randl .

Дайте мне знать, если я должен объяснить больше. У меня также есть несколько реализаций numpy для сложных производных.

Еще одна полезная операция (особенно для проектов в области физики, требующих поддержки комплексных чисел) — это обработчик оператора exp() . В тензорном потоке у нас есть tf.exp(x + iy) = tf.exp(x) * (tf.cos(y) + 1j * tf.sin(y)) . Это просто реализовать и в pytorch?

@sunilkpai , @boeddeker , @Randl ,

Спасибо за отчет о комплексных производных. Я постараюсь следовать этому и вернусь к этому на следующей неделе. Я подумал, что добавлю сюда несколько ссылок и опишу статус проекта.

Статус комплексных чисел поддерживается неофициально и должен быть добавлен через расширение PyTorch:

Каждое расширение содержит две вещи:

  • .cpp , который содержит все необходимые регистрации математического ядра.
  • Папка test/ , содержащая очень упрощенные версии тестовых сценариев pytorch.
    Посмотрите в тестовых сценариях, какие ядра поддерживаются (и почему другие не поддерживаются).

Почему я не могу вывести на консоль сложный тензор?

  • Объект Tensor python имеет красивое форматирование, которое вызывает некоторые неподдерживаемые функции.

    • Вы можете изменить содержимое tensor.py , чтобы обойти форматирование печати.

    • Или вы можете просто преобразовать тензоры Pytorch в массивы Numpy, а затем распечатать.

Текущий статус проекта:

  • Покрытие процессора довольно хорошее.

    • Ядра реализованы внутри PyTorch в разделе 'aten/src/ATen/native/cpu/ </li> <li>Complex number specific code is under 'aten/src/ATen/native/cpu/zmath.h

    • Ускорение Intel AVX256 находится в разделе «aten/src/ATen/cpu/vec256/»



      • @sunilkpai : я не знал об оптимизации exp. Это папка, куда вы добавляете это.


      • Дайте мне знать, если вам удобно вносить изменения.



  • Покрытие GPU ограничено бинарными и унарными операциями:

    • Ядра реализованы внутри PyTorch в разделе 'aten/src/ATen/native/cuda/* </li> <li>Complex number specific code is under 'aten/src/ATen/native/cuda/zmath.cuh

    • Используются типы данных thrust::complex<T> , включая оптимизированные ядра.

Текущее развитие:

  • Ожидание переноса ядер TH на основе C в папку C++ ATen.

    • Функция rand() необходима для переноса тестовых случаев на внутренние тесты pytorch.

    • Некоторые операции индексирования в настоящее время не перенесены.

    • В настоящее время имеется 168/1300 математических ядер (по сравнению с 230 в октябре), которые необходимо перенести с TH на ATen.

  • Я постараюсь добавить поддержку комплексных чисел, когда эти ядра станут доступны в ATen.

--

к вашему сведению. Что касается сложных деривативов, у нас было долгое обсуждение в Джулии, и его реализация теперь находится в ChainRules (см. . Как правило, людям нужно только
\partial L/\partial adjoint(z) в качестве градиента (по определению это самое быстрое направление убывания), но производная отличается от \partial L/\partial z , следует добавить дополнительный интерфейс, если мы хотим полную поддержку комплексного числа AD . Для получения подробных правил вы можете проверить, что реализовано в ChainRules или Zygote/lib (поскольку существуют только общие правила, нет отдельных правил для комплексных чисел для большинства операторов, обратный проход для вещей например, matmul записываются в общем определении, например, adjoint(A) * B )

Почему я не могу вывести на консоль сложный тензор?
Объект Tensor python имеет красивое форматирование, которое вызывает некоторые неподдерживаемые функции.
Вы можете изменить содержимое tensor.py, чтобы обойти форматирование печати.
Или вы можете просто преобразовать тензоры Pytorch в массивы Numpy, а затем распечатать.

Я думаю, что исправил хотя бы часть печати в https://github.com/Roger-luo/pytorch-complex для отладки и т. д. в первую очередь, не уверен, что это поможет, поскольку мастер сильно изменился в прошлом год. Вы можете просто взять это, если это полезно, я не собираюсь больше этим заниматься.

@dylanbespalko У меня относительно мало опыта работы с внутренностями pytorch, хотя я начал учиться! Я мог бы попробовать это изменение, хотя, основываясь на том, что я вижу в aten/src/ATen/cpu/vec256/* , я не уверен, необходимо ли это, учитывая, что поведение std::exp(std::complex) по умолчанию - это именно то, что я упомянул. в моем предыдущем комментарии: см. примечания https://en.cppreference.com/w/cpp/numeric/complex/exp . Я также не уверен, как это переводится в реализацию этих операций в CUDA (которая в настоящее время кажется ограниченной реальными, imag, conj и angle?).

@sunilkpai ,

Я добавил поддержку AVX для exp() , используя предоставленное уравнение.

Я также заметил, что некоторые вещи были сломаны из-за некоторых недавних изменений в PyTorch. Я исправил это в #30871.

@dylanbespalko

Есть ли сроки переноса с TH на ATen?
Могу ли я внести свой вклад, учитывая тот факт, что я плохо разбираюсь во внутренней работе pytorch?

Я нашел формулу для обратного распространения комплекса svd в архиве и мог бы реализовать это, если вы покажете мне, где

Спасибо за вашу работу!

@Jakob-Unfried

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

Ядра TH реализованы на языке C, и добавление туда сложной поддержки не представляет особого интереса из-за присущих ему проблем с подсчетом ссылок. Вы можете отслеживать прогресс в aten/src/ATen/native/native_functions.yaml , где зарегистрировано каждое ядро:

Найдите legacy::cpu::_th и разделите это число на 3, чтобы получить количество старых ядер TH.
Найдите legacy::cpu::_thnn и разделите это число на 3, чтобы получить количество старых ядер нейронной сети TH.

Каждое ядро ​​обычно регистрируется тремя разными способами:
1. Обычное ядро ​​y = add(a, b)
2. Ядро на месте a = add_(a, b)
3. Вывод ядра add_out(a, b, out=y)
Фактическая реализация всегда находится в ядре вывода, а другие 2 вызывают эту функцию.

Ядра nn, как правило, легче портировать, потому что у них меньше зависимых ядер. Следовательно, если вы можете портировать ядра в порядке, обратном тому, как они были реализованы, то вы будете делать меньше общей работы.

Проверка проблемы с отслеживанием переноса https://github.com/pytorch/pytorch/issues/24507 , также cc @VitalyFedyunin

Вот обновление статуса поддержки комплексных чисел в соответствии с запросом #32437. Сегодня я снова работаю над поддержкой процессора.

Поддержка Автограда

  • У меня не было много времени для этого.
  • angle() , real() , imag() , conj() были реализованы.
  • abs() потребует отдельной реализации для комплексных чисел. (см. примечания от @boeddeker и @Randl выше)

Аппаратная поддержка

В настоящее время поддержка комплексных чисел реализована вне дерева. Вот что это значит:

Код внутри дерева

  • Математические операции фактически реализованы в дереве (внутри исходного кода PyTorch).
  • Ни один из тестов Pytorch внутри дерева не проверяет поддержку сложных чисел (поэтому все ломается).
  • PyTorch переходит с TH на ATen (#24507).
    - Математические ядра, реализованные в TH, не поддерживают комплексные числа.
    - Только ядра, реализованные в ATen, могут поддерживать комплексные числа.
  • Вам необходимо установить расширение PyTorch, чтобы включить сложный dtype.

Код вне дерева

  • Несколько расширений PyTorch реализованы и могут быть легко внедрены в будущем:
  • Каждое расширение имеет четыре важных файла:

    • setup.py: соберите и установите расширение pytorch.

    • [CPU/CUDA/FPGA]ComplexType.cpp: регистрация математического ядра аналогична CPUType.cpp или CUDAType.cpp.

    • test/test_torch.py: очень уродливые тестовые случаи, которые показывают, какие ядра работают, ограничены поддержкой ATen.

    • test/test_autograd.py: тестирование функциональности автограда.

Расширения PyTorch вне дерева

  1. cpu_strided_complex
    - [x]Копировать ядро
    - [ ] TensorFactories (th_random, th_uniform, th_normal)
    - [x] RangeFactory
    - [x] BinaryOpKernals
    - [x] UnaryOpKernels
    - [x] Сравните OpKernels
    - [x] PowKernels
    - [x] ReduceOpKernels (th_min, th_max, некоторые нормы не вычисляют комплексно-сопряженные значения)
    - [ ] IndexOpKernels (th_masked_select_bool, th_set, th_gather, th_cat)
    - [x] PointwiseOps
    - [x] Операции лерпов
    - [ ] BlasOps (th_mv, th_mm, th_fmod, th_eig)
    - [ ] LinpackOps (использует Blas)
    - [ ] SpectralOps (поддерживается, но требует доработки)

    1. cuda_strided_complex



      • [x] Копировать ядро


      • [ ] TensorFactory (см. проблемы с процессором)


      • [x] BinaryOpKernals


      • [x] UnaryOpKernels (Задание: добавить угол, реальный, имаг, кондж)


      • [ ] CompareOpKernels (Todo)


      • [ ] ReduceOpKernels (сообщения об ошибках, касающихся WARP_SIZE)


      • Графический процессор становится сложным за пределами точечных вычислений, однако могут поддерживаться дополнительные функции.



  2. vitis_strided_complex

    • Xilinx Vitis — это платформа синтеза высокого уровня FPGA, которая поддерживает серверные и встроенные устройства.

    • Выпущено в октябре 2019 г. (вероятно, ограниченная поддержка устройств).

    • Сочетает SDAccel (сервер) с VIvado HLS (встроенный).

    • [ ] BinaryOpKernals (конец января)

    • [ ] UnaryOpKernels (конец января)

    • [ ] ReduceOpKernels (конец февраля).

    • Недавно добавленные FPGA поддерживают векторизованные объекты, аналогичные классу шаблонов Vec256 PyTorch.

    • Vec256 был тем, как сложная поддержка была добавлена ​​​​в ЦП, и это кажется более естественным способом реализации тензорных пространств $C$ или $R^N$.

Дополнительные обновления по этому вопросу: https://github.com/pytorch/pytorch/issues/33152

Это может заслуживать или не заслуживать отдельного вопроса, но я был бы признателен за просмотр и думаю, что в настоящее время практически более важно иметь в документации что-то, что объясняет, «как pytorch работает с комплексными числами прямо сейчас». aka может выполнять сложение, умножение, какую-то норму, не может иметь комплексные веса и т. д. Все это можно резюмировать несколькими строками документации, объясняющей, каково предполагаемое текущее поведение высокого уровня.

Это может заслуживать или не заслуживать отдельного вопроса, но я был бы признателен за просмотр и думаю, что в настоящее время практически более важно иметь в документации что-то, что объясняет, «как pytorch работает с комплексными числами прямо сейчас». aka может выполнять сложение, умножение, какую-то норму, не может иметь комплексные веса и т. д. Все это можно резюмировать несколькими строками документации, объясняющей, каково предполагаемое текущее поведение высокого уровня.

Привет @redwrasse спасибо за отзыв! в настоящее время у нас есть примечание для комплексных чисел, в котором рассказывается о некоторых основах факелов и сложных функциях, поддерживаемых для сложных тензоров на мастере.
(большинство из которых включены в выпуск 1.6) https://pytorch.org/docs/master/complex_numbers.html?highlight=complex. Можете ли вы поделиться, какие еще функции вас интересуют? рад рассказать больше о нашей текущей поддержке и планах на будущие выпуски.

Это может заслуживать или не заслуживать отдельного вопроса, но я был бы признателен за просмотр и думаю, что в настоящее время практически более важно иметь в документации что-то, что объясняет, «как pytorch работает с комплексными числами прямо сейчас». aka может выполнять сложение, умножение, какую-то норму, не может иметь комплексные веса и т. д. Все это можно резюмировать несколькими строками документации, объясняющей, каково предполагаемое текущее поведение высокого уровня.

Привет @redwrasse спасибо за отзыв! в настоящее время у нас есть примечание для комплексных чисел, в котором рассказывается о некоторых основах факелов и сложных функциях, поддерживаемых для сложных тензоров на мастере.
(большинство из которых включены в выпуск 1.6) https://pytorch.org/docs/master/complex_numbers.html?highlight=complex. Можете ли вы поделиться, какие еще функции вас интересуют? рад рассказать больше о нашей текущей поддержке и планах на будущие выпуски.

Спасибо @anjali411 , приятно видеть эту документацию, раньше я о ней не знал. Я думаю, что необходимо выделить несколько строк по центру «текущее состояние поддержки сложных нейронных сетей», но позвольте мне пройтись по ним...

Людям, интересующимся сложным автоградом, вас может заинтересовать https://github.com/pytorch/pytorch/issues/41857 , в котором говорится о том, какому соглашению будет следовать PyTorch (JAX или TF).

Была ли эта страница полезной?
0 / 5 - 0 рейтинги