SlideShare a Scribd company logo
1 of 34
Download to read offline
Functional “Life”:
parallel cellular automata and comonads
Alexander Granin
graninas@gmail.com
C++ Russia, Saint Petersburg
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++
struct Presentation
{
Functional programming in С++
Functionally designed cellular automation
Parallel computation of cellular automation
};
4
Functional programming in C++
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>
С++ User Group Novosibirsk, 2014
“Functional Declarative Design in C++”
С++ 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
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...
9
Simple 1-dimensional 3-state CA
● 1 dimension
● 3 states: A (“Alive”), P (“Pregnant”), D/space (“Dead”),
A A
A A
A A
P
P
A A A
1 gen P
2 gen A A A
3 gen A A A A
4 gen A P A
5 gen A A A
6 gen A A A A
7 gen A P A
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;
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
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
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;
}
Applying rule: extend, extract
Cell rule (Universe<Cell> row);
Universe<Cell> extend (
std::function<Cell(Universe<Cell>)> f,
const Universe<Cell>& u);
Cell extract(const Universe<Cell>& u);
A A A A
P
P
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,
const Universe<Cell>& u);
Universe<Universe<Cell>>
duplicate (const Universe<Cell>& u);
Universe<Cell> left (const Universe<Cell>& u);
Universe<Cell> right (const Universe<Cell>& u);
Universe<Cell> r1;
r1.position = 0;
r1.field = {D, D, D, P, D, D, D};
Universe<Cell> r2 = stepWith(rule(), r1);
Universe<Cell> r3 = stepWith(rule(), r2);
Universe<Cell> (
std::function<Cell(Universe<Cell>)> f,
const Universe<Cell>& u) {
return extend(f, ut);
}
Step
17
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)
Generic extract
template <typename T> T extract(const UT& u)
{
return u.field[u.position];
}
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 };
}
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;
}
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);
}
Generic makeUniverse
template <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 };
}
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)
24
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);
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();
}
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
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
28
Parallel Game of Life benchmark
● 2 dimensions
● 2 states: A (“Alive”), D/space (“Dead”),
// Pointed array of pointed arrays
typedef Universe<Cell> LifeRow;
typedef Universe<LifeRow> LifeField;
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)
extend vs extend2
template <typename T> UT extend (
const func<T(UT)>& f,
const UT& u) {
UUT duplicated = duplicate (u);
return { map (f, duplicated.field), u.position }; // == fmap (f, duplicated.field)
}
template <typename T> UUT extend2 (
const func<T(UUT)>& f,
const UUT& uut) {
UUUUT duplicated = duplicate2 (uut);
return fmap2 (f, duplicated);
}
fmap2
template <typename T> UUT fmap2 (
const func<T(UUT)>& f,
const UUUUT& uuut) {
const func<UT(UUUT)> f2 = [=](const UUUT& uuut2) {
UT newUt;
newUt.position = uuut2.position;
newUt.field = map (f, uuut2.field);
return newUt;
};
return { map (f2, uuut.field), uuut.position }; // parallelization: map -> mapPar
}
Game of Life benchmark
Field side Sequential Parallel
(milliseconds)
50 484 283
100 3900 2291
150 12669 8005
200 30278 19415
auto l1 = gliderLifeHuge();
QBENCHMARK {
auto l2 = stepWith(rule, l1);
QVERIFY(l2.size() == HugeSize);
}
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
Thank you!
Alexander Granin
graninas@gmail.com
Questions?
C++ Russia, Saint Petersburg

More Related Content

What's hot

Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithmAho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Takatoshi Kondo
 

What's hot (20)

Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notes
 
Алексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляАлексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуля
 
Day 1
Day 1Day 1
Day 1
 
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithmAho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
 
Bind me if you can
Bind me if you canBind me if you can
Bind me if you can
 
Academy PRO: ES2015
Academy PRO: ES2015Academy PRO: ES2015
Academy PRO: ES2015
 
Es.next
Es.nextEs.next
Es.next
 
JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)
 
Kirk Shoop, Reactive programming in C++
Kirk Shoop, Reactive programming in C++Kirk Shoop, Reactive programming in C++
Kirk Shoop, Reactive programming in C++
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
 
Dynamic C++ ACCU 2013
Dynamic C++ ACCU 2013Dynamic C++ ACCU 2013
Dynamic C++ ACCU 2013
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Data
 
Objective-Cひとめぐり
Objective-CひとめぐりObjective-Cひとめぐり
Objective-Cひとめぐり
 
Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”
 
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic LabsTypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
 
The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210
 
openFrameworks 007 - utils
openFrameworks 007 - utilsopenFrameworks 007 - utils
openFrameworks 007 - utils
 
EcmaScript 6
EcmaScript 6 EcmaScript 6
EcmaScript 6
 
响应式编程及框架
响应式编程及框架响应式编程及框架
响应式编程及框架
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 

Similar to Functional "Life": parallel cellular automata and comonads

I want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdfI want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdf
bermanbeancolungak45
 
This is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdfThis is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdf
kostikjaylonshaewe47
 
I am trying to create a program That works with two other programs i.pdf
I am trying to create a program That works with two other programs i.pdfI am trying to create a program That works with two other programs i.pdf
I am trying to create a program That works with two other programs i.pdf
fortmdu
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
league
 

Similar to Functional "Life": parallel cellular automata and comonads (20)

The STL
The STLThe STL
The STL
 
Operators
OperatorsOperators
Operators
 
Java operators
Java operatorsJava operators
Java operators
 
Rcpp11 genentech
Rcpp11 genentechRcpp11 genentech
Rcpp11 genentech
 
C++ extension methods
C++ extension methodsC++ extension methods
C++ extension methods
 
I want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdfI want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdf
 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
 
PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...
 
C++11 - STL Additions
C++11 - STL AdditionsC++11 - STL Additions
C++11 - STL Additions
 
This is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdfThis is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdf
 
Lecture 9_Classes.pptx
Lecture 9_Classes.pptxLecture 9_Classes.pptx
Lecture 9_Classes.pptx
 
I am trying to create a program That works with two other programs i.pdf
I am trying to create a program That works with two other programs i.pdfI am trying to create a program That works with two other programs i.pdf
I am trying to create a program That works with two other programs i.pdf
 
C++11
C++11C++11
C++11
 
Introduction to c part 2
Introduction to c   part  2Introduction to c   part  2
Introduction to c part 2
 
131 Lab slides (all in one)
131 Lab slides (all in one)131 Lab slides (all in one)
131 Lab slides (all in one)
 
Oop objects_classes
Oop objects_classesOop objects_classes
Oop objects_classes
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
 
Ray Tracing with ZIO
Ray Tracing with ZIORay Tracing with ZIO
Ray Tracing with ZIO
 
New C# features
New C# featuresNew C# features
New C# features
 
2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading
 

More from Alexander Granin

More from Alexander Granin (20)

Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stm
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
Final tagless vs free monad
Final tagless vs free monadFinal tagless vs free monad
Final tagless vs free monad
 
Monadic parsers in C++
Monadic parsers in C++Monadic parsers in C++
Monadic parsers in C++
 
The present and the future of functional programming in c++
The present and the future of functional programming in c++The present and the future of functional programming in c++
The present and the future of functional programming in c++
 
О разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop development
 
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...
 
Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...
 
Закон Деметры / Demetra's law
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's law
 
Design of big applications in FP
Design of big applications in FPDesign of big applications in FP
Design of big applications in FP
 
GitHub - зеркало разработчика
GitHub - зеркало разработчикаGitHub - зеркало разработчика
GitHub - зеркало разработчика
 
The Present and The Future of Functional Programming in C++
The Present and The Future of Functional Programming in C++The Present and The Future of Functional Programming in C++
The Present and The Future of Functional Programming in C++
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNsk
 
Transition graph using free monads and existentials
Transition graph using free monads and existentialsTransition graph using free monads and existentials
Transition graph using free monads and existentials
 
Software transactional memory. pure functional approach
Software transactional memory. pure functional approachSoftware transactional memory. pure functional approach
Software transactional memory. pure functional approach
 
Вы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FPВы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FP
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
 
Линзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция даннымиЛинзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция данными
 
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)
 
Идиоматичный функциональный код
Идиоматичный функциональный кодИдиоматичный функциональный код
Идиоматичный функциональный код
 

Recently uploaded

Jax, FL Admin Community Group 05.14.2024 Combined Deck
Jax, FL Admin Community Group 05.14.2024 Combined DeckJax, FL Admin Community Group 05.14.2024 Combined Deck
Jax, FL Admin Community Group 05.14.2024 Combined Deck
Marc Lester
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 

Recently uploaded (20)

Lessons Learned from Building a Serverless Notifications System.pdf
Lessons Learned from Building a Serverless Notifications System.pdfLessons Learned from Building a Serverless Notifications System.pdf
Lessons Learned from Building a Serverless Notifications System.pdf
 
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product UpdatesGraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
 
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
 
AI Hackathon.pptx
AI                        Hackathon.pptxAI                        Hackathon.pptx
AI Hackathon.pptx
 
Microsoft365_Dev_Security_2024_05_16.pdf
Microsoft365_Dev_Security_2024_05_16.pdfMicrosoft365_Dev_Security_2024_05_16.pdf
Microsoft365_Dev_Security_2024_05_16.pdf
 
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
 
The Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion ProductionThe Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion Production
 
Jax, FL Admin Community Group 05.14.2024 Combined Deck
Jax, FL Admin Community Group 05.14.2024 Combined DeckJax, FL Admin Community Group 05.14.2024 Combined Deck
Jax, FL Admin Community Group 05.14.2024 Combined Deck
 
Optimizing Operations by Aligning Resources with Strategic Objectives Using O...
Optimizing Operations by Aligning Resources with Strategic Objectives Using O...Optimizing Operations by Aligning Resources with Strategic Objectives Using O...
Optimizing Operations by Aligning Resources with Strategic Objectives Using O...
 
The Evolution of Web App Testing_ An Ultimate Guide to Future Trends.pdf
The Evolution of Web App Testing_ An Ultimate Guide to Future Trends.pdfThe Evolution of Web App Testing_ An Ultimate Guide to Future Trends.pdf
The Evolution of Web App Testing_ An Ultimate Guide to Future Trends.pdf
 
Odoo vs Shopify: Why Odoo is Best for Ecommerce Website Builder in 2024
Odoo vs Shopify: Why Odoo is Best for Ecommerce Website Builder in 2024Odoo vs Shopify: Why Odoo is Best for Ecommerce Website Builder in 2024
Odoo vs Shopify: Why Odoo is Best for Ecommerce Website Builder in 2024
 
Reinforcement Learning – a Rewards Based Approach to Machine Learning - Marko...
Reinforcement Learning – a Rewards Based Approach to Machine Learning - Marko...Reinforcement Learning – a Rewards Based Approach to Machine Learning - Marko...
Reinforcement Learning – a Rewards Based Approach to Machine Learning - Marko...
 
The Strategic Impact of Buying vs Building in Test Automation
The Strategic Impact of Buying vs Building in Test AutomationThe Strategic Impact of Buying vs Building in Test Automation
The Strategic Impact of Buying vs Building in Test Automation
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
KLARNA -  Language Models and Knowledge Graphs: A Systems ApproachKLARNA -  Language Models and Knowledge Graphs: A Systems Approach
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
 
Community is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea GouletCommunity is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea Goulet
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024
 
How to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabberHow to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabber
 
SQL Injection Introduction and Prevention
SQL Injection Introduction and PreventionSQL Injection Introduction and Prevention
SQL Injection Introduction and Prevention
 

Functional "Life": parallel cellular automata and comonads

  • 1. Functional “Life”: parallel cellular automata and comonads Alexander Granin graninas@gmail.com C++ Russia, Saint Petersburg
  • 2. 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++
  • 3. struct Presentation { Functional programming in С++ Functionally designed cellular automation Parallel computation of cellular automation };
  • 5. 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>
  • 6. С++ User Group Novosibirsk, 2014 “Functional Declarative Design in C++”
  • 7. С++ 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
  • 8. 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...
  • 9. 9 Simple 1-dimensional 3-state CA ● 1 dimension ● 3 states: A (“Alive”), P (“Pregnant”), D/space (“Dead”), A A A A A A P P A A A 1 gen P 2 gen A A A 3 gen A A A A 4 gen A P A 5 gen A A A 6 gen A A A A 7 gen A P A
  • 10. 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;
  • 11. 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
  • 12. 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
  • 13. 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; }
  • 14. Applying rule: extend, extract Cell rule (Universe<Cell> row); Universe<Cell> extend ( std::function<Cell(Universe<Cell>)> f, const Universe<Cell>& u); Cell extract(const Universe<Cell>& u); A A A A P P
  • 15. 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, const Universe<Cell>& u); Universe<Universe<Cell>> duplicate (const Universe<Cell>& u); Universe<Cell> left (const Universe<Cell>& u); Universe<Cell> right (const Universe<Cell>& u);
  • 16. Universe<Cell> r1; r1.position = 0; r1.field = {D, D, D, P, D, D, D}; Universe<Cell> r2 = stepWith(rule(), r1); Universe<Cell> r3 = stepWith(rule(), r2); Universe<Cell> ( std::function<Cell(Universe<Cell>)> f, const Universe<Cell>& u) { return extend(f, ut); } Step
  • 17. 17 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)
  • 18. Generic extract template <typename T> T extract(const UT& u) { return u.field[u.position]; }
  • 19. 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 }; }
  • 20. 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; }
  • 21. 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); }
  • 22. Generic makeUniverse template <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 }; }
  • 23. 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)
  • 24. 24 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);
  • 25. 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(); }
  • 26. 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
  • 27. 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
  • 28. 28 Parallel Game of Life benchmark ● 2 dimensions ● 2 states: A (“Alive”), D/space (“Dead”), // Pointed array of pointed arrays typedef Universe<Cell> LifeRow; typedef Universe<LifeRow> LifeField;
  • 29. 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)
  • 30. extend vs extend2 template <typename T> UT extend ( const func<T(UT)>& f, const UT& u) { UUT duplicated = duplicate (u); return { map (f, duplicated.field), u.position }; // == fmap (f, duplicated.field) } template <typename T> UUT extend2 ( const func<T(UUT)>& f, const UUT& uut) { UUUUT duplicated = duplicate2 (uut); return fmap2 (f, duplicated); }
  • 31. fmap2 template <typename T> UUT fmap2 ( const func<T(UUT)>& f, const UUUUT& uuut) { const func<UT(UUUT)> f2 = [=](const UUUT& uuut2) { UT newUt; newUt.position = uuut2.position; newUt.field = map (f, uuut2.field); return newUt; }; return { map (f2, uuut.field), uuut.position }; // parallelization: map -> mapPar }
  • 32. Game of Life benchmark Field side Sequential Parallel (milliseconds) 50 484 283 100 3900 2291 150 12669 8005 200 30278 19415 auto l1 = gliderLifeHuge(); QBENCHMARK { auto l2 = stepWith(rule, l1); QVERIFY(l2.size() == HugeSize); }
  • 33. 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