Знай я, что слово "асинхронный" вызовет такое непопадание в смысл, просто не стал бы его использовать... И несмотря на то, что я попытался определить термины в следующем посте, всё равно появляются комментарии про то, что я "путаю две вещи" и "асинхронность и multicore ортогональны". Постараюсь обясниться яснее и короче.

Повторюсь цитатой из предыдущего поста:

Ещё один термин, которому не повезло — асинхронность. По-настоящему она означает вызов функции, которая не делает всей своей работы сразу, а быстро возвращает управление в вызвавшую программу, выполняя свои вычисления параллельно с ней. Никакого конкретного способа реализации такого параллелизма не предполагается.

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

Уважамые комментаторы! Я не писал пост про асинхронный I/O. Этот вопрос вполне себе решён библиотеками уже сейчас, и проблем не вызывает. Я писал про асинхронное всё остальное, чего у нас ещё нет. Про распараллеливание любых алгоритмов: начиная от элементарной сортировки и до алгоритма поведения игрового мира с сотнями юнитов. Я не хочу спорить про правомерность употребления слова "асинхронность" в этом контексте. Если оно вам не нравится, просто используйте слово "параллельность". Или "concurrency".

Но только не пишите мне про ввод-вывод, пожалуйста :-)

Комментарии: 18

  1. david-m.livejournal.com

    Иван, но ведь и в фокусе с yield и в node.js весь код программы исполняется по прежнему строго в один поток. Это — физически —именно асинхронность (не-синхронность с системными вызовами), но не параллелизм.

  2. Ivan Sagalaev

    Во-первых надо уточнить, что фокус с yield не связан напрямую с темой про глобальный параллелизм. Это просто мысль в голову пришла.

    Во-вторых, асинхронность всегда означает параллелизм. Даже если это I/O. При асинхронном I/O основной код программы исполняется в один поток, но I/O-то идёт с ней параллельно. То, что это происходит не в ещё одном треде — это просто удачная деталь реализации. Но повторюсь, это не то, о чём я проповедую :-)

  3. shadone

    асинхронность часто подразумевает событийность, возможно термин event-driven будет к месте и более понятен.

  4. hodzanassredin

    offtopic заметил тренд в блоге "провоцирующие " посты, которые вызывают интересные комментарии, этакий провоцирующий data mining :-) Жаль, что работает только с умными подписчиками. Очень интересно, жду продолжений на другие темы. ;-)

  5. Денис Баженов

    Во-вторых, асинхронность всегда означает параллелизм.

    Я согласен с ddenis. Асинхронность не всегда означает параллелизм. Асинхронность с успехом используют с тех времен когда SMP не существовало в принципе. Более того, верно и обратное - не все формы параллелизма сводятся к асинхронности. Вот сведите мне пожалуйста SIMD параллелизм к асинхронности.

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

    В первой заметке вы привели в пример С + GCD и Erlang. В этих двух языках принципиально разные модели обеспечения конкурентного исполнения: erlang - модель actor'ов, GCD тупой thread pool дополненный syntax sugar для удобства работы. В моем понимании ничего общего между ними не существует.

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

    А иначе это все из разряда "из пустого в порожнее"...

  6. Александр Несказов

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

    Асинхронность означает то, что указанное действие будет где-нибудь, как-нибудь, когда-нибудь выполнено.

    И рядом для синхронности:

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

  7. http://maxidoors.ru/

    Ваня, извини, но про ввод-вывод напишу. Дисковый и sendfile он до сих пор плохо-асинхронный. Т.е. если с сетевыми сокетами вопрос худо-бедно решен, то с диском ещё нет.

    Теперь насчет коллбеков и прочего. Я с тобой полностью несогласен. Я последние полгода работаю больше с EventMachine, чем с рельсами и могу сказать, что это очень, очень, невообразимо неудобно, особенно по сравнению с эрлангом. На каждый чих вместо content = http.get("http://ya.ru") писать http.get("http://ya.ru", :onresult => :content, :onerror => :error) очень муторно.

    Результат этого прост: DNS вызовы всё равно везде блокируют код.

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

  8. Ivan Sagalaev

    На каждый чих вместо content = http.get("http://ya.ru") писать http.get("http://ya.ru", :onresult => :content, :onerror => :error) очень муторно.

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

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

    Я именно для этого в Clojure смотрю.

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

    Это очень условное "сейчас". Оно есть, но оно не мейнстрим. А мейнстрим — это Java с тредами над разделяемой памятью и локами. А на вебе — PHP с синхронизацией данных через запись их в БД.

  9. Денис Баженов

    Я именно для этого в Clojure смотрю.

    А Scala не смотрели? Он выглядит более прагматично.

  10. http://maxidoors.ru/

    Ваня, не нужны новые языки.

    Руби 1.8 с патчами или 1.9 уже могут делать сопрограмность правильно.
    Тот же эрланг, которому я в последнее время уделяю много времени http://github.com/maxlapshin/erlyvideo отличается, но в целом о том же.

    А теперь смотри, есть большая кодовая база на руби. Берем файберы, в нужных местах втыкаем шедулинг и получаем то, о чём ты просишь сразу.

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

  11. Ivan Sagalaev

    А теперь смотри, есть большая кодовая база на руби. Берем файберы, в нужных местах втыкаем шедулинг и получаем то, о чём ты просишь сразу.

    Нет, Макс, мы получаем все те же проблемы с потерей времени на локах, дед-локами и рейс-кондишенами, которые имеем сейчас во всех остальных языках. До тех пор, пока твой язык работает с mutable-данными, это засада.

  12. http://maxidoors.ru/

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

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

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

  13. Виталий

    Асинхронность - характеристика процессов, не совпадающих во времени.
    Это надо же какая засада получается.
    На самом деле синхронность в таком случае - лишь частный случай асинхронности(сравните с детерминизмом/недетерминизмом по Дейкстре), также как Порядок - частный случай Хаоса(зато какой случай!).
    И не асинхронность нужно реализовывать, исходя из синхронщины(треды, локи и т.д.), а наоборот.
    Поэтому - Erlang и иже с ним будут рулить в будущем. По крайней мере этот вывод логично следует.
    Программисты ведь постепенно переходят на то, что позволяет экономить время на разработку, и этот фактор в первую очередь экономически обоснован, а когда в дело вмешиваются деньги, вопрос долго не стоит.
    P.S.: Хотя сам я за Python :-)
    И, таки да. Асинхронность порождает параллелизм, но не требует его постоянного существования. Выполнил параллельно асинхронный участок кода, пожалуйста, можешь прибить эту ветку, а можешь оставить.
    Может эту мысль имели в виду и Иван, и.. и другие? :-)
    А может недостаточно четко определено понятие параллелизма?
    Что это: выполнение одной функции в программе параллельно основному потоку, или модель построения программы, при которой она представляет из себя несколько параллельно работающих веток, имеющих возможности для общения между собой, или вообще фиолетовые огурцы?
    Если есть треды с локами, то подлинной асинхронности нет, всегда возможна необходимость одновременного доступа к залоченному объекту нескольких потоков.
    В фокусе Ивана с yield, как изволили выразиться, если такая необходимость возникнет, то вопрос, куда денется асинхронность?

  14. Денис Баженов

    Те, у кого Скала доходит до продакшна, обычно это либо знают, либо не хотят признаться

    Немного не понял вашу мысль. Можете уточнить?

    Вообще, мне непонятны мотивы ваших нападок на java. Безусловно, это императивный язык, который не способствует написанию кода, который будет легко параллелится, — с этим глупо спорить. Но никто же не мешает вам использовать в java и immutable типы и клонирование где надо и message passing и кооперативную многозадачность. Весь этот инструментарий есть. И тогда не будет у вас deadlock'ов. Это проблема программиста, а не языка. Мне кажется, что наличие у языка GIL гораздо более "страшная" проблема чем отсутствие поддержки "единственно правильного и святого" подхода? Вам так не кажется? :)

    P.S. Кстати, у меня сложилось впечатление что для вас deadlock'и это самая большая проблема многопоточного программирования. Deadlock'и находятся и диагностируются очень легко и быстро (ну по-крайней мере в java). Гораздо быстрее чем некоторые ошибки в бизнес-логике.

  15. Геннадий

    Прошу прощения за "непрограммность". Интересно было прочитать
    о столь привычных электронщику понятиях в приложении к программированию. В радиоэлектронике "синхронный" - это когда передающей стороне безразлично, успевает ли приёмная сторона принимать/обрабатывать передаваемую информацию и включен ли приёмник. Пример: телевидение. "Асинхронный" - передатчик запрашивает у приёмника подтверждение о получении порции данных. Пример: передача факса.

  16. HunteX

    А знаете, очень интересные разговоры тут ... Дайте как я тоже ченить предложу ... А почему бы не дать задачу "распараллеливания" (правильно написал или нет - не знаю ;)) железу? Для себя я заметил, что чем больше в коде асинхронности - тем ужасней он становится (.
    Вот, например на хабре статейка http://habrahabr.ru/company/intel/blog/78350/, там говорится про бла-бла-бла ... "инструменты, которые помогут реализовать распараллеливание и оптимизацию кода на языке Си++, даже если вы не имеете полного представления о принципах работы программы", в чем я ОЧЕНЬ сомневаюсь, так как незнание принципов работы своей же программы (в каких участках кода наибольшая/наименьшая нагрузка и т.п.) ни к чему хорошему не приведет. Скажем так: имеется программа, которую мы хотим разрезать распаралелить. Так давайте поручим это железке, которая, при большой нагрузке (неявно) начинает "рубить" программу на отдельные части (потоки), или же резать код, указанный явно программистом в нужных нам местах (скачка файла в бэкграунде и т.п.)

    p.s. пишу на C# 1 год - так что отнеситесь с пониманием :)

  17. bialix

    Геннадий, как электронщик вынужден указать вам, что всё не так.

    Вы говорите о передаче с подтверждением и без подтверждения приёма. Это к синхронности/асинхронности имеет ортогональное отношение.

  18. Google user

    HunteX, сделайте прототип, поймёте насколько это сложно.

Добавить комментарий