Александр Гранин, Функциональная 'Жизнь':...
TRANSCRIPT
![Page 1: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/1.jpg)
Functional “Life”:parallel cellular automata and comonads
Alexander [email protected]
C++ Russia, Saint Petersburg
![Page 2: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/2.jpg)
Who I am?
● C++, Haskell, C#
● C++ User Group Novosibirsk, 2014“Functional Declarative Design in C++”
● C++ Siberia Novosibirsk, 2015“Functional Microscope: Lenses in C++”
● Talks, articles, research on FP in general, FP in C++
![Page 3: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/3.jpg)
struct Presentation{
Functional programming in С++Functionally designed cellular automationParallel computation of cellular automation
};
![Page 4: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/4.jpg)
4
Functional programming in C++
![Page 5: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/5.jpg)
C++ FP Enthusiasts● Range v3 by Eric Niebler - proposal for C++ Standard Lib
● FTL (Functional Template Library) by Bjorn Aili
● Cat by Nicola Bonelli - Category Theory elements
● Bartosz Milewski
● John Carmack
● …
● <Place your name here>
![Page 6: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/6.jpg)
С++ User Group Novosibirsk, 2014“Functional Declarative Design in C++”
![Page 7: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/7.jpg)
С++ Siberia Novosibirsk, 2015“Functional Microscope: Lenses in C++”
auto lens = personL() to addressL() to houseL();
Account account1 = {...};Account account2 = set(lens, account1, 20);// account2.person.address.house == 20
std::function<int(int)> modifier =[](int old) { return old + 6; };
Account account3 = over(lens, account2, modifier);// account3.person.address.house == 26
Lens 2 Lens 3Lens 1
![Page 8: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/8.jpg)
FP elements in C++
● Lambdas, closures, functions (almost pure)
● std::function<>
● Immutability, POD-types
● Templates - pure functional language
● for_each(), recursion
● C++ Concepts: coming soon...
![Page 9: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/9.jpg)
9
Simple 1-dimensional 3-state CA
● 1 dimension
● 3 states: A (“Alive”), P (“Pregnant”), D/space (“Dead”),
A AA A
A A
P
P
A A A
1 gen P2 gen A A A3 gen A A A A4 gen A P A5 gen A A A6 gen A A A A7 gen A P A
![Page 10: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/10.jpg)
template <typename T>struct Universe { std::vector<T> field; int position;};
typedef char Cell;
const Cell Pregnant = 2;const Cell Alive = 1;const Cell Dead = 0;
Universe<Cell>
A A A A
Universe<T>: Pointed array
Universe<Cell> u;u.field = {D, A, A, D, A, A, D};u.position = 3;
![Page 11: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/11.jpg)
Immutable shift
A A A A
Universe<Cell> left (const Universe<Cell>& u) {
Universe<Cell> newU { u.field, u.position - 1 };
if (u.position == 0) newU.position = u.size() - 1;
return newU;}
Universe<Cell> right (const Universe<Cell>& u);
A A A A
A A A A
shift to right
shift to left
![Page 12: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/12.jpg)
Observing: shift and extract
A A A A
Cell extract(const Universe<Cell>& u) { return u.field[u.position];}
Universe<Cell> u = {...};
Cell cur = extract (u);
Cell r = extract (right (u));Cell rr = extract (right (right (u)));
Cell l = extract (left (u));Cell ll = extract (left (left (u)));
D
A A A A
shift to left
shift to left
extract
![Page 13: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/13.jpg)
Rule: observe and reduce
A A A A
P
Cell rule(const Universe<Cell>& row) {
// extract l, ll, cur, r, rr here if (isA(l) && isA(r) && !isAorP(cur)) return Pregnant;
// ... more rules here
return Dead;}
![Page 14: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/14.jpg)
Applying rule: extend, extractCell rule (Universe<Cell> row)
Universe<Cell> extend ( std::function<Cell(Universe<Cell>)> f, Universe<Cell> u)
A A A A
P
P
![Page 15: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/15.jpg)
Step: duplicate, (for_each: extend, extract)
A A A A
A A A A
A A A A
A A A A
A A A A
A A A A
A A A A A
P
A
A
P
A
Cell rule (Universe<Cell> row)
Universe<Cell> extend ( std::function<Cell(Universe<Cell>)> f, Universe<Cell> u)
Universe<Universe<Cell>>duplicate (Universe<Cell> u)
Universe<Cell> left (Universe<Cell> u)Universe<Cell> right (Universe<Cell> u)
![Page 16: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/16.jpg)
16
Generic functional approach
#define UT Universe<T>#define UUT Universe<Universe<T>>
template <typename T> T rule (const UT& u)
template <typename T> UT left (const UT& u)template <typename T> UT right (const UT& u)
![Page 17: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/17.jpg)
Generic extract
template <typename T> T extract(const UT& u){ return u.field[u.position];}
![Page 18: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/18.jpg)
Generic extend
template <typename T> UT extend ( const func<T(UT)>& f, const UT& u) { UUT duplicated = duplicate (u); return { map(f, duplicated.field), u.position };}
![Page 19: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/19.jpg)
Generic map
template<typename A, typename B, template <class ...> class Container>Container<B> map ( const std::function<B(A)>& f, const Container<A>& va){ Container<B> vb; std::transform(va.begin(), va.end(), std::back_inserter(vb), f); return vb;}
![Page 20: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/20.jpg)
Generic duplicate
const std::function<UT(UT)> leftCreator = [](const UT& u) {return left(u); };const std::function<UT(UT)> rightCreator = [](const UT& u) {return right(u); }; template <typename T> UUT duplicate (const UT& u){ return makeUniverse (leftCreator, rightCreator, u);}
![Page 21: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/21.jpg)
Generic makeUniversetemplate <typename T> UUT makeUniverse ( const std::function<UT(UT)>& leftCreator, const std::function<UT(UT)>& rightCreator, const UT& u) { std::vector<UT> lefts = tailOfGen(u.position, leftCreator, u); std::vector<UT> rights = tailOfGen(u.size() - u.position - 1, rightCreator, u);
std::vector<UT> all; all.swap(lefts); all.push_back(u); all.insert(all.end(), rights.begin(), rights.end());
return { std::move(all), u.position };}
![Page 22: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/22.jpg)
extract + duplicate + extend = comonad
template <typename T> T extract (const UT& u)
template <typename T> UT extend ( const func<T(UT)>& f, const UT& u)
template <typename T> UUT duplicate (const UT& u)
![Page 23: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/23.jpg)
23
Parallel computations in FP
Container<B> map ( const std::function<B(A)>& f, const Container<A>& va);
Container<B> mapPar ( const std::function<B(A)>& f, const Container<A>& va);
![Page 24: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/24.jpg)
mapPar
template <typename A, typename B, template <class ...> class Container>Container<B> mapPar ( const std::function<B(A)>& f, const Container<A>& va){ Container<std::future<B>> pars = map(par(f), va); std::future<Container<B>> pRes = joinPars(pars); return pRes.get();}
![Page 25: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/25.jpg)
template <typename A, typename B> std::function<std::future<B>(A)> par( const std::function<B(A)>& f){ return [=](const A& a) { return std::async(std::launch::async, [=]() { return f(a); } ); };}
par
![Page 26: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/26.jpg)
template <typename B> std::future<std::vector<B>> joinPars( std::vector<std::future<B>>& pars){ return std::async(std::launch::async, [&]() { std::vector<B> bs; bs.reserve(pars.size());
for (auto& it : pars) bs.push_back(it.get());
return bs; });}
joinPars
![Page 27: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/27.jpg)
27
Parallel Game of Life benchmark
● 2 dimensions
● 2 states: A (“Alive”), D/space (“Dead”),
// Pointed array of pointed arraystypedef Universe<Cell> LifeRow;typedef Universe<LifeRow> LifeField;
![Page 28: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/28.jpg)
A little bit harder...#define UT Universe<T>#define UUT Universe<Universe<T>>#define UUUT Universe<Universe<Universe<T>>>#define UUUUT Universe<Universe<Universe<Universe<T>>>>
template <typename T> UUUUT duplicate2 (const UUT& u)
template <typename T> UUT extend2 ( const func<T(UUT)>& f, const UUT& u)
template <typename T> T extract2 (const UUT& u)
![Page 29: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/29.jpg)
extend vs extend2template <typename T> UT extend ( const func<T(UT)>& f, const UT& u){ UUT duplicated = duplicate (u); return { map (f, duplicated.field), u.position };}
template <typename T> UUT extend2 ( const func<T(UUT)>& f, const UUT& uut){ UUUUT duplicated = duplicate2 (uut); return fmap2 (f, duplicated);}
![Page 30: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/30.jpg)
fmap2
template <typename T> UUT fmap2 ( const func<T(UUT)>& f, const UUUUT& uuut){ const func<UT(UUUT)> f2 = [=](const UUUT& uuut2) { // Something really complicated here with using of ‘f’. };
return { map (f2, uuut.field), uuut.position }; // parallelization: map -> mapPar}
![Page 31: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/31.jpg)
Game of Life benchmark
Field side Sequential Parallel(microseconds)
50 484 283100 3900 2291150 12669 8005200 30278 19415
![Page 32: Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и комонады в C++](https://reader030.vdocuments.site/reader030/viewer/2022020410/586fb21c1a28abe57d8b6773/html5/thumbnails/32.jpg)
Game of Life on comonads, C++
● Highly experimental
● Sequential, async and parallel GoL
● Simple 1D 3-state CA
● Functional design
● https://github.com/graninas/CMLife
● Клеточные автоматы и комонады, by Hithroc Mehatoko