[personal profile] sassa_nf
В императивных языках учитывается модель памяти. Это такая вещь, которая приводит в соответствие program order и platform memory order.

Так вот. Это не функциональные программы хорошо параллелизуются, ибо иммутабельные данные. Это функциональные программы трудно писать с мутабельными данными, ибо в них остутствует этот самый program order.

Date: 2012-12-06 12:14 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
Это не так. Порядок не имеет значения не из-за ленивости, а из-за, хм, чёрч-россеровости нетипизированного лямбда-исчисления с WHNF. Стимулирует повышение паралеллизма чистота, возникающая из-за иммутабельности, чёрч-россеровости, ссылочной прозрачности и других факторов. В ленивых вычислениях необходима чёрч-россеровость, чтобы семантика кода не менялась от статического контекста, в который он синтаксически вложен, иначе неудобно. В хаскеле придумали (посредством монад, но существуют и др. решения), как сохранить чёрч-россеровость при наличии мутабельности.

Как-то так.
Edited Date: 2012-12-06 12:15 pm (UTC)

Date: 2012-12-06 01:33 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Я не пойму, на параллелизм влияет что-либо, кроме разрешения reordering вычислений? Можно ли сказать тогда, что ленивость - это предел разрешения reordering? Такая вот самая obvious фича, которая составляет самый relaxed порядок из partial order вычислений.

Чистота, чёрч-россеровость, ссылочная прозрачноть тоже попадалось в списке похвал функциональщине, но я пока не понял, как это сочетается с линеаризацией.

Я на академичность не претендую, но очень польщён просвещением.

Date: 2012-12-06 02:48 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
> Можно ли сказать тогда, что ленивость - это предел разрешения reordering?

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

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

Расширенные возможности по reordering - это свойство чистых программ, а не ленивых. Скажем, mapreduce допускает реордеринг.

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

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

Иммутабельность способствует чистоте (и реордерингу), но возможна чистота вместе с мутабельностью (IORef в хаскеле).

К паралеллизму всё вышесказанное имеет, однако, весьма косвенное отношение.

Для паралеллизма важно, чтобы все программы из threads interleaving space имели одну и ту же семантику. Этому как раз способствует immutability. Если вы будете в хаскеле использовать IORefs (чистота без immutability) многопоточно, то получите по голове теми же проблемами с изменением семантики в зависимости от интерливинга, что и в императивных программах.

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

Date: 2012-12-06 03:42 pm (UTC)
From: [identity profile] thesz.livejournal.com
>Ленивость как таковая вообще не допускает reordering.

Допускает. Это вот normal order evaluation не допускает ("всегда внутренний левый"), а lazy evaluation (graph reduction) допускает.

Date: 2012-12-06 04:15 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
К сожалению, стандарт не предписывает хаскелю какой-то определённой семантики и допускает различные толкования - т.е. формально можно выбирать из десятков лямбда-исчислений и систем редукции графов на свой вкус.

Общепринято считать семантикой функциональной части хаскеля call by need lambda calculus with whnf (формально это другое исчисление по сравнению с call by need lambda calculus with nf), а семантикой императивной - семантику из tackling the squad.

Lazy evaluation и call by need lambda calculus - это одно и то же. "Normal order reduction" - это call by name lambda calculus.

Системы редукции графов могут быть использована как формализм (clean), так и как средство реализации call by need (haskell). Общепринято как раз считать редукцию графов деталью реализации ghc. Call by need прекрасно описывается через дырки (evaluation contexts) безо всяких графов или через interaction nets, которые, насколько мне известно, не являются TGRS в общепринятом смысле.

Т.е. это вопрос договорённости. Общепринято, что семантика хаскеля (включая потребление ресурсов) - это редукция в нормальном порядке, реализация всего лишь может её оптимизировать.

Но в принципе, можно считать и что семантика хаскеля - это редукция до whnf, а какую нормализирующую стратегию использовать - неспецифицированно.

Можно спросить в кафе, пусть нас рассудят :)

Date: 2012-12-06 04:04 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
"Для паралеллизма важно, чтобы все программы из threads interleaving space имели одну и ту же семантику."

о. вот это и есть linearizability.


"Компилятор может слегка отклоняться от порядка, предписываемого ленивостью"

Хм, я думал, ленивость не предписывает порядок, ибо статьи о реализации рассуждают о возможности исполнять что-то спекулятивно, и что есть общая очередь спарков, которые должны сейчас выполняться, и что "агенты"=железные потоки выполняют любой спарк по одному, а потому о предписываемом порядке вычислений говорить сложно.

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

Или в каком смысле тогда порядок предписан?


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


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

Ага, хорошо. Агду пока страшно :)

Тогда этот пост о том, что я обнаружил, что reordering в хаскеле > reordering в императиве.


Ну, и спасибо за экскурс. Теперь понятно, почему никто не мог ответить "какая в хаскелле модель памяти?" - потому что на самом деле нужно искать литературу по чёрч-россеровости и сильным норальным формам.

Date: 2012-12-06 04:41 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
> нужно искать литературу по чёрч-россеровости
> и сильным норальным формам.

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

Date: 2012-12-06 05:05 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
> Blackholing - это, конечно, всего-лишь
> реализация концепции не-повторения вычислений.

Тут важно, что ленивостью предписано, в каких случаях вычисления повторяются, а в каких нет. Это не "автоматическая дедупликация всего", а жесткие и очень примитивные синтаксические правила, вроде того как в Си жестко задано, что longFunction в int x = longFunction(); for (;;) { }; вычисляется один раз если снаружи цикла, и столько раз сколько отрабатывает цикл, если внутри.

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

Да, для тонкого управления есть strictness annotations, и в высокопроизводительном коде приходится подсказывать компилятору.

Date: 2012-12-06 05:15 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
> я обнаружил, что reordering в
> хаскеле > reordering в императиве.

Ага. Но не по той причине, и к паралеллизму не относится.

> Теперь понятно, почему никто не мог ответить
> "какая в хаскелле модель памяти?"

Система типов позволяет реализовывать произвольные модели памяти, и есть достаточно много разных библиотек с разными моделями:

http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism

Есть все традиционные и все экзотические модели :)

Наиболее интересные на мой взгляд - это

Cloud Haskell
Software Transactional Memory
CHP: Communicating Haskell Processes
Repa

Date: 2012-12-06 05:27 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
> о. вот это и есть linearizability

Это называется serializability (of interleaving).

> Или в каком смысле тогда порядок предписан?

В таком же смысле, в каком он предписан в императивных языках. Если вы пишете

x = 5;
y = 6;
return x;


То предписано, что сначала делается x = 5, потом y = 6, потом return x.

Но если компилятор может доказать, что перестановка ничего не меняет - то он может всё попересталять:

return 5;
y = 6;
x = 5;

Но от этого никто не говорит, что в императивных программах порядок выполнения не определён :) И при написании программы рассуждает так, как будто порядок именно такой, как он написал и не рассматривает всевозможные эквивалентные порядки.

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

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

Date: 2012-12-06 06:05 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
"Это называется serializability (of interleaving)."

здесь пересечение терминологии, по-видимому. Я о линеаризации в смысле как здесь: Linearizability: A Correctness Condition for Concurrent Objects, M. Herlihy and J.Wing, Proceedings of 14th ACM Symposium on Principles of Programming Languages, 1987


"Но от этого никто не говорит, что в императивных программах порядок выполнения не определён :) И при написании программы рассуждает так, как будто порядок именно такой, как он написал и не рассматривает всевозможные эквивалентные порядки."

Да, понятный пример. Тогда да, я думаю лишь о реализации, дающей результат, эквивалентный какому-то там каноническому, который я ещё не изучал.

Date: 2012-12-10 12:56 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
А каким боком чёрч-россеровость к параллелизму? "Отклоняться от порядка редукций" всё-таки говорит о _порядке_ редукций, коего у параллельного graph reduction как бы и нет. Кто-то где-то должен был бы доказать параллельную теорему Чёрча-Россера :)

Date: 2012-12-10 01:29 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
> А каким боком чёрч-россеровость к параллелизму?

Никаким. Я же так и писал - "весьма косвенное отношение".

"Отклоняться от порядка редукций" ничего не значит, т.к. это нестрогая формулировка, объяснение на пальцах. Ознакомьтесь со строгой версией.

http://wiki.clean.cs.ru.nl/Functional_Programming_and_Parallel_Graph_Rewriting - 3 глава про системы перезаписи графов, и 5 глава про concurrency. У пиратов есть в пдф одним куском.

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

См. также
- The Call-by-Need Lambda Calculus by John Maraist, Martin Odersky, Philip Wadler;
- http://research.microsoft.com/en-us/um/people/simonpj/papers/marktoberdorf/ (4 глава)
- http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.27.3918

и т. д.

Ещё учтите, что Parallelism != Concurrency и tackling the squad посвящён concurrency, а вы говорите именно о паралеллизме. И MPI is all about parallelism, but Erlang is all about concurrency.

Отвечая непосредственно на ваш вопрос - есть теоремы о возможности параллельных редукций с сохранением семантики.
Edited Date: 2012-12-10 01:52 pm (UTC)

Date: 2012-12-10 01:59 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
ой, какая замечательная книжка!

Date: 2012-12-10 02:13 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
Я начинал с сикпа и с неё

Profile

sassa_nf

February 2026

S M T W T F S
1234567
891011121314
15161718192021
222324252627 28

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 22nd, 2026 03:26 am
Powered by Dreamwidth Studios