Computation Expressions
От: WolfHound  
Дата: 05.05.10 13:16
Оценка:
Я там маленько порефакторил (разнес код по файлам) и сделал простенький но очень удобный движек для тестов.
Сейчас нужно все обложить тестами и тогда можно будет сдеать чтобы трансформация шла через промежуточную модель.
2dsorokin займешся?
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Computation Expressions
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.10 13:32
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>...и сделал простенький но очень удобный движек для тестов.


А зачем?

Есть же test.n.

Если со временем перенесем этот код в стандартную библиотеку макросов, то нужно будет использовать именно его.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Computation Expressions
От: dsorokin Россия  
Дата: 05.05.10 14:27
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Сейчас нужно все обложить тестами и тогда можно будет сдеать чтобы трансформация шла через промежуточную модель.

WH>2dsorokin займешся?

Я планировал сначала async из f# приручить. Билдер для Немерле уже существует, но нужен еще модуль для запуска вычислений и некоторые асинхронные расширения к паре стандартных классов. По сути это будет оболочка над f#-повским async. Здесь же проверится в целом возможность интегрироваться с workflow из f#, которую я считаю важной.

Тесты мне понравились. Кстати, я там еще в самом начале внес ошибку в метод Combine. Первый аргумент на самом деле должен иметь тип M[FakeVoid] или M[Unit], где Unit из f#. Это лучше исправить. И, вообще, мне ужасно не нравится название FakeVoid, но ничего лучше пока не придумал. Название Unit занято за f#. Еще думаю, что можно избавиться от поля FakeVoid.Value. Можно просто null передавать, хотя это не совсем правильно использовать null вместо значения с точки зрения теории ф.п., но похоже, что f# внутри так и поступает со своим Unit.
Re[2]: Computation Expressions
От: dsorokin Россия  
Дата: 05.05.10 14:28
Оценка:
Здравствуйте, dsorokin, Вы писали:

D> Кстати, я там еще в самом начале внес ошибку в метод Combine. Первый аргумент на самом деле должен иметь тип M[FakeVoid] или M[Unit], где Unit из f#. Это лучше исправить.


Ошибка в тестах, а не в макросе.
Re[2]: Computation Expressions
От: WolfHound  
Дата: 05.05.10 15:19
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Я планировал сначала async из f# приручить.

Мне честно говоря async из F# не понравился совсем.
Его делали явно теоретики которые реальную многопоточность в глаза не видели.
За привязку к одному пулу потоков нужно канделябром по рукам. Это эпикфейл который делает всю либо малополезной.
Да и просто криво проектирован.

Я сейчас выношу свой мозг CPS'ом после чего сделаю свой async.

D>Можно просто null передавать, хотя это не совсем правильно использовать null вместо значения с точки зрения теории ф.п., но похоже, что f# внутри так и поступает со своим Unit.

По хорошему генерики должны параметризоваться void'ом, а на физическом уровне вообще ничего не должно передаваться. Но CLR писали дуболомы и он так не умеет.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Computation Expressions
От: dsorokin Россия  
Дата: 05.05.10 15:43
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Я сейчас выношу свой мозг CPS'ом после чего сделаю свой async.


Что-то ты добрый сегодня Кстати, внутри async сидит три продолжения: (1) для основного потока вычислений, (2) для обработки ошибок и (3) для экстренной отмены вычислений.

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

Вообще, async — довольно таки сложная штука. Там должно быть много подводных камней. В той же оптимизации хвостовой рекурсии не все так гладко. Внутри async используют, например, FakeUnit вместо unit из-за этого. Что-то там не так с виртуальной машиной дот-нета. На мой взгляд проще использовать уже готовое решение в виде async через небольшую оболочку, чем писать заново аналог.
Re[4]: Computation Expressions
От: WolfHound  
Дата: 05.05.10 16:05
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Что-то ты добрый сегодня

Я? Добрый? Не замечал.

D>Кстати, внутри async сидит три продолжения: (1) для основного потока вычислений, (2) для обработки ошибок и (3) для экстренной отмены вычислений.

Я в курсе.

D>А в привязке к одному системному пулу есть свой смысл. Новый поток создается на новую длительную асинхронную операцию, и как я понимаю, вызвавший поток отдается пулу (??). То есть, обычно заняты те потоки, которые выполняют что-то тяжеловесное. А ресурсы компьютера ограничены. Поэтому имеет смысл использовать ограниченное количество рабочих потоков. Если я прав в своем представлении, то такая схема выглядит логичной.

В теории.
Проблема в том что я провел два года на галерах в Яндексе и знаю что одного пула потоков хватает только в самых примитивных ситуациях.
Если же у нас логика чуть сложнее то одним пулом не отделаться.
Ибо появляются проблемы с откликом и дедлоки в том числе распределенные.

D>Вообще, async — довольно таки сложная штука. Там должно быть много подводных камней. В той же оптимизации хвостовой рекурсии не все так гладко. Внутри async используют, например, FakeUnit вместо unit из-за этого. Что-то там не так с виртуальной машиной дот-нета. На мой взгляд проще использовать уже готовое решение в виде async через небольшую оболочку, чем писать заново аналог.

Там единственная сложность это загнать вычисления в довольно хитрый CPS.
Тк я плохо понимаю CPS эта часть идет туго. Но как только разберусь что к чему все остальное сделаю за несколько часов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Computation Expressions
От: dsorokin Россия  
Дата: 05.05.10 16:46
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Проблема в том что я провел два года на галерах в Яндексе и знаю что одного пула потоков хватает только в самых примитивных ситуациях.

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

Честно говоря, не вижу причин для дедлоков. Впрочем, у меня нет богатого опыта в этой области.

WH>Там единственная сложность это загнать вычисления в довольно хитрый CPS.


Это как раз оказалось просто Но я с этим разбирался отдельно, и это заняло некоторое время.
Re[6]: Computation Expressions
От: WolfHound  
Дата: 06.05.10 10:51
Оценка:
Здравствуйте, dsorokin, Вы писали:

WH>>Там единственная сложность это загнать вычисления в довольно хитрый CPS.

D>Это как раз оказалось просто Но я с этим разбирался отдельно, и это заняло некоторое время.
Короче я забил на CPS и сделал по рабоче-крестьянски.
Получилось совсем просто и подозреваю заметно быстрее чем в версии F#.
Набросок я закомитил.
В финальной версии отучу его на каждый шаг бегать по всему стеку. Это не сложно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Computation Expressions
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.05.10 11:30
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Я планировал сначала async из f# приручить.


Это плохая идея хотя бы потому, что заставляет таскать с собой лишнюю сботку. Потом еще не ясно не нарушит ли такое таскание лицензии f#. Ведь рантайм f#-а с дотнетом не поставляется.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Computation Expressions
От: dsorokin Россия  
Дата: 06.05.10 11:43
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Короче я забил на CPS и сделал по рабоче-крестьянски.

WH>Получилось совсем просто и подозреваю заметно быстрее чем в версии F#.
WH>Набросок я закомитил.
WH>В финальной версии отучу его на каждый шаг бегать по всему стеку. Это не сложно.

У меня есть сомнения в том, что это несложно. А не придешь ли к необходимости того же самого CPS, которого сейчас хочешь избежать?

Получается, что где-то глубоко в локальном месте на каждом шаге ты либо редуцируешь вычисление типа Async, либо возвращаешь значение. И тут нужно передать управление выше по стеку вызовов, но это именно то, что может делать CPS.
Re[3]: Computation Expressions
От: dsorokin Россия  
Дата: 06.05.10 11:50
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Это плохая идея хотя бы потому, что заставляет таскать с собой лишнюю сботку. Потом еще не ясно не нарушит ли такое таскание лицензии f#. Ведь рантайм f#-а с дотнетом не поставляется.


С .NET v4, насколько знаю, поставляется (это не powerpack). Что касается более ранних версий, то можно требовать самостоятельной установки F# разработчиком и ручного компилирования такого переходника. Тогда, наверное, лицензия не будет нарушена. То есть, поставлять переходник в исходниках.
Re[7]: Computation Expressions
От: dsorokin Россия  
Дата: 06.05.10 12:07
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Набросок я закомитил.


Обработку while можно написать короче для ContBuilder:

    public While[A, R](pred : void -> bool, body : Cont[A, R]) : Cont[A, R]
      where A : new()
    {
      if (pred ())
        Bind (body, () => While (pred, body))
      else
        Zero ()
    }


Вот, с foreach дело обстоит сложнее. Для него нужен using, который в свою очередь выражается через try-finally. А для try-finally нужно уже второе продолжение для обработки ошибок.
Re[5]: Computation Expressions
От: dsorokin Россия  
Дата: 06.05.10 12:13
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Там единственная сложность это загнать вычисления в довольно хитрый CPS.


Между прочим, могу поделиться своей реализацией Cont, но на f#. Там используется два продолжения: одно для основного потока, другое — для обработки ошибок. Все это вместе позволяет реализовать все конструкции.
Re[8]: Computation Expressions
От: WolfHound  
Дата: 06.05.10 12:21
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>У меня есть сомнения в том, что это несложно.

Не надо сомневаться.
Берем код:
  [Record]
  public class AsyncBind[A, B] : Async[B]
  {
    private mutable async : Async[A];
    private cont : A -> Async[B];
    public override Exec(job : AsyncJob, _res : ref B) : Async[B]
    {
      mutable r;
      async = async.Exec(job, ref r);
      if (async == null)
        cont(r);
      else
        this;
    }
  }

И меняем так:
      async = job.ExecWhileReady(async, ref r);

ExecWhileReady будет выполнять код пока не дойдет до конца или не встретит Async который ждет результата.

D>А не придешь ли к необходимости того же самого CPS, которого сейчас хочешь избежать?

Нет.

D>Получается, что где-то глубоко в локальном месте на каждом шаге ты либо редуцируешь вычисление типа Async, либо возвращаешь значение. И тут нужно передать управление выше по стеку вызовов, но это именно то, что может делать CPS.

Я это и без CPS могу.
См код. Сейчас такая передача управления происходит каждый шаг.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Computation Expressions
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.05.10 12:25
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>С .NET v4, насколько знаю, поставляется (это не powerpack).


Нет. Не поставляется.

D> Что касается более ранних версий, то можно требовать самостоятельной установки F# разработчиком и ручного компилирования такого переходника.


Что мягко говоря очень неудобно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Computation Expressions
От: dsorokin Россия  
Дата: 06.05.10 12:43
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>ExecWhileReady будет выполнять код пока не дойдет до конца или не встретит Async который ждет результата.


А как в твоем случае будет реализована такая важная фича продолжений: умение прерываться в одном потоке и возобновляться в другом?
Re[10]: Computation Expressions
От: WolfHound  
Дата: 06.05.10 12:55
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>А как в твоем случае будет реализована такая важная фича продолжений: умение прерываться в одном потоке и возобновляться в другом?

Ты вот этот код видел?
Если очень захочется каждую итерацию можно проводить в отдельном потоке
    public static ExecAll(job : AsyncJob, mutable async : Async[A]) : A
    {
      mutable res;
      while (async != null)
        async = async.Exec(job, ref res);
      res;
    }
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[11]: Computation Expressions
От: dsorokin Россия  
Дата: 06.05.10 13:11
Оценка:
Здравствуйте, WolfHound, Вы писали:

D>>А как в твоем случае будет реализована такая важная фича продолжений: умение прерываться в одном потоке и возобновляться в другом?


WH>Если очень захочется каждую итерацию можно проводить в отдельном потоке


Но ведь переключаться на другой поток нужно будет внутри Exec (и внутри job.ExecWhileReady), если я правильно понимаю задачу async.
Re[12]: Computation Expressions
От: WolfHound  
Дата: 06.05.10 13:30
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Но ведь переключаться на другой поток нужно будет внутри Exec (и внутри job.ExecWhileReady), если я правильно понимаю задачу async.

Взводим внутри job флажек и вываливаемся на самый верх.
После чего спокойно переключаемся.
Думаю этого хватит:
    public enum JobState
    {
      | Ready
      | SwitchContext
      | Wait
      | Canceled
    }

Внутри ExecWhileReady проверяем что флаг == Ready, а уже на верхнем уровне разбираемя что произошло.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.