433 lines
15 KiB
HTML
433 lines
15 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
|
|
<title>CSE 662 - Languages and Runtimes for Big Data</title>
|
|
|
|
<meta name="description" content="Material for the University at Buffalo's CSE-662 'Languages and Runtimes for Big Data'">
|
|
<meta name="author" content="Oliver Kennedy">
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
|
|
<link rel="stylesheet" href="../reveal.js-3.7.0/css/reveal.css">
|
|
<link rel="stylesheet" href="../reveal.js-3.7.0/css/theme/moon.css" id="theme">
|
|
|
|
<!-- Theme used for syntax highlighting of code -->
|
|
<link rel="stylesheet" href="../reveal.js-3.7.0/lib/css/zenburn.css">
|
|
|
|
<!-- Printing and PDF exports -->
|
|
<script>
|
|
var link = document.createElement( 'link' );
|
|
link.rel = 'stylesheet';
|
|
link.type = 'text/css';
|
|
link.href = window.location.search.match( /print-pdf/gi ) ? '../reveal.js-3.7.0/css/print/pdf.css' : '../reveal.js-3.7.0/css/print/paper.css';
|
|
document.getElementsByTagName( 'head' )[0].appendChild( link );
|
|
</script>
|
|
|
|
<!--[if lt IE 9]>
|
|
<script src="lib/js/html5shiv.js"></script>
|
|
<![endif]-->
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="reveal">
|
|
|
|
<!-- Any section element inside of this container is displayed as a slide -->
|
|
<div class="slides">
|
|
<section>
|
|
<section>
|
|
<h2>Functional Data Structures</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Reminder</h3>
|
|
<p>Learned Index Structures due Weds (in class)</p>
|
|
<p>One person from each group should email me...<ul>
|
|
<li>[CSE-662] in the subject line</li>
|
|
<li>A list of group members (Names + UBITs)</li>
|
|
<li>The project seed that your group would like to work on</li>
|
|
</ul></p>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<section>
|
|
<p><span class="fragment highlight-red">Mutable</span> vs Immutable Data</p>
|
|
</section>
|
|
|
|
<section>
|
|
<pre><code>
|
|
X = [ "Alice", "Bob", "Carol", "Dave" ]
|
|
</code></pre>
|
|
|
|
<table class="fragment">
|
|
<tr>
|
|
<td style="font-size: 120%; font-weight: bold; font-family: fixed">X : </td>
|
|
<td style="border-style: solid; border-width: 5px;">Alice</td>
|
|
<td style="border-style: solid; border-width: 5px;">Bob</td>
|
|
<td style="border-style: solid; border-width: 5px;">Carol</td>
|
|
<td style="border-style: solid; border-width: 5px;">Dave</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<pre><code class="fragment">
|
|
print(X[2]) // -> "Carol"
|
|
</code></pre>
|
|
|
|
<pre><code class="fragment">
|
|
X[2] = "Eve"
|
|
</code></pre>
|
|
|
|
<table class="fragment">
|
|
<tr>
|
|
<td style="font-size: 120%; font-weight: bold; font-family: fixed">X : </td>
|
|
<td style="border-style: solid; border-width: 5px;">Alice</td>
|
|
<td style="border-style: solid; border-width: 5px;">Bob</td>
|
|
<td style="border-style: solid; border-width: 5px; color: white; border-color: white">Eve</td>
|
|
<td style="border-style: solid; border-width: 5px;">Dave</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<pre><code class="fragment">
|
|
print(X[2]) // -> "Eve"
|
|
</code></pre>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<pre><code>
|
|
X = [ Alice, Bob, Carol, Dave ]
|
|
</code></pre>
|
|
|
|
<table>
|
|
<tr>
|
|
<td style="font-size: 120%; font-weight: bold; font-family: fixed">X : </td>
|
|
<td style="border-style: solid; border-width: 5px;">Alice</td>
|
|
<td style="border-style: solid; border-width: 5px;">Bob</td>
|
|
<td style="border-style: solid; border-width: 5px;">Carol</td>
|
|
<td style="border-style: solid; border-width: 5px;">Dave</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<table style="margin-top: 80px">
|
|
<thead class="fragment">
|
|
<th style="width: 300px; text-align: center;">Thread 1</th>
|
|
<th style="width: 300px; text-align: center;">Thread 2</th>
|
|
</thead>
|
|
<tr>
|
|
<td><pre><code>
|
|
X[2] = "Eve"
|
|
</code></pre></td>
|
|
<td><pre><code>
|
|
print(X[2])
|
|
</code></pre></td>
|
|
</tr>
|
|
<tr class="fragment"><td></td><td style="font-size: 300%;text-align: center">🤔</td></tr>
|
|
</table>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Mutable Data Structures</h3>
|
|
<ul>
|
|
<li class="fragment">The programmer's intended ordering is unclear.</li>
|
|
<li class="fragment">Atomicity/Correctness requires locking.</li>
|
|
<li class="fragment">Versioning requires copying the data structure.</li>
|
|
<li class="fragment">Cache coherency is expensive.</li>
|
|
</ul>
|
|
<p style="font-weight: bold; margin-top: 50px;" class="fragment">Can these problems be avoided?</p>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<section>
|
|
<p>Mutable vs <span class="fragment highlight-red">Immutable Data</span></p>
|
|
</section>
|
|
|
|
<section>
|
|
<pre><code>
|
|
X = [ "Alice", "Bob", "Carol", "Dave" ]
|
|
</code></pre>
|
|
|
|
<table>
|
|
<tr>
|
|
<td style="font-size: 120%; font-weight: bold; font-family: fixed">X : </td>
|
|
<td style="border-style: solid; border-width: 5px;">Alice</td>
|
|
<td style="border-style: solid; border-width: 5px;">Bob</td>
|
|
<td style="border-style: solid; border-width: 5px;">Carol</td>
|
|
<td style="border-style: solid; border-width: 5px;">Dave</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<pre><code class="fragment" data-fragment-index="1">
|
|
print(X[2]) // -> "Carol"
|
|
</code></pre>
|
|
|
|
<pre><code class="fragment fade-in-then-semi-out" data-fragment-index="1">
|
|
X[2] = "Eve"
|
|
</code></pre>
|
|
|
|
<p style="font-weight: bold; margin-top: 50px;" class="fragment">Don't allow writes!</p>
|
|
|
|
<p style="font-weight: bold; margin-top: 50px;" class="fragment">But what if we need to update the structure?</p>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Idea 1: Copy</h3>
|
|
|
|
<table>
|
|
<tr>
|
|
<td style="font-size: 120%; font-weight: bold; font-family: fixed">X : </td>
|
|
<td>Alice</td>
|
|
<td>Bob</td>
|
|
<td>Carol</td>
|
|
<td>Dave</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<table>
|
|
<tr>
|
|
<td style="font-size: 120%; font-weight: bold; font-family: fixed">X' : </td>
|
|
<td class="fragment">Alice</td>
|
|
<td class="fragment">Bob</td>
|
|
<td class="fragment">Eve</td>
|
|
<td class="fragment">Dave</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p style="font-weight: bold; margin-top: 50px;" class="fragment">Slooooooooooooooooooooooow!</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Idea 2: Break it Down</h3>
|
|
<svg data-src="graphics/2018-08-31-FunctionalTreeInsertion.svg" height="500px" style="background-color: lightgrey;" />
|
|
<p class="fragment">Data is always added, not replaced!</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h4>Immutable Data Structures
|
|
<div style="font-size: 50%">(aka 'Functional' or 'Persistent' Data Structures)</div></h4>
|
|
<ul>
|
|
<li class="fragment">Once an object is created it never changes.</li>
|
|
<li class="fragment">The object persists until all pointers to it go away, at which point it is garbage collected.</li>
|
|
<li class="fragment">Only the "root" pointer is ever allowed to change, to point to a new version.</li>
|
|
</ul>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<section>
|
|
<h2>Linked List Stacks</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<svg data-src="graphics/2018-08-31-FunctionalStack.svg" width="796px" height="493px" style="background-color: lightgrey;" stretch/>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<section>
|
|
<h2>Class Exercise 1</h2>
|
|
|
|
<p>How would you implement:</p>
|
|
<pre><code>
|
|
list update(list, index, new_value)
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Class Exercise 2</h2>
|
|
|
|
<p>Implement a set with:</p>
|
|
<pre><code>
|
|
set init()
|
|
boolean is_member(set, elem)
|
|
set insert(set, elem)
|
|
</code></pre>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<section>
|
|
<h3 class="fragment" data-fragment-index="2">Lazy Evaluation</h3>
|
|
<img src="graphics/2018-08-31-FunctionalStackMerge.svg" style="background-color: lightgrey" />
|
|
|
|
<p class="fragment" data-fragment-index="1">Can we do better?</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Putting off Work</h3>
|
|
|
|
<table>
|
|
<tr>
|
|
<td style="vertical-align: middle; font-size: 150%;"><pre>x = "expensive()"</pre></td>
|
|
<td class="fragment" style="text-align: center;">Fast<br/>(Just saving a 'todo')</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="vertical-align: middle; font-size: 150%;"><pre>print(x)</pre></td>
|
|
<td class="fragment" style="text-align: center;">Slow<br/>(Performing the 'todo')</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="vertical-align: middle; font-size: 150%;"><pre>print(x)</pre></td>
|
|
<td class="fragment" style="text-align: center;">Fast<br/>('todo' already done)</td>
|
|
</tr>
|
|
</table>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Class Exercise 3</h2>
|
|
<img src="graphics/2018-08-31-FunctionalStackMerge.svg" style="background-color: lightgrey" />
|
|
|
|
<p>Make it better!</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Putting off Work</h3>
|
|
<pre><code>
|
|
concatenate(a, b) {
|
|
a', front = pop(a)
|
|
if a' is empty {
|
|
return (front, b)
|
|
} else {
|
|
return (front, "concatenate(a', b)")
|
|
}
|
|
}
|
|
</code></pre>
|
|
|
|
<p class="fragment">What is the time complexity of this concatenate?</p>
|
|
<p class="fragment">What happens to reads?</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Lazy Evaluation</h3>
|
|
<p>Save work for later...
|
|
<ul>
|
|
<li>... and avoid work that is never requred.</li>
|
|
<li>... to spread out work over multiple calls.</li>
|
|
<li>... for better "amortized" costs.</li>
|
|
</ul>
|
|
</p>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<section>
|
|
<h3>Amortized Analysis</h3>
|
|
<p>Allow operation A to 'pay it forward' for another operation B that hasn't happened yet.</p>
|
|
|
|
<p class="fragment">... or allow an operation B to 'borrow' from another operation A that hasn't happened yet.</p>
|
|
|
|
<ul class="fragment">
|
|
<li>A's time complexity goes up by X.</li>
|
|
<li>B's time complexity goes down by X.</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h4>Example: Amortized Queues</h4>
|
|
|
|
<img src="graphics/2018-08-31-AmortizedQueue.svg" style="background-color: lightgrey" height="600px" />
|
|
</section>
|
|
|
|
<section>
|
|
<h4>Example: Amortized Queues</h4>
|
|
|
|
<pre><code>
|
|
queue enqueue(queue, item) {
|
|
return {
|
|
current : queue.current,
|
|
todo : push(queue.todo, item)
|
|
)
|
|
}
|
|
</code></pre>
|
|
<p class="fragment">What is the cost?</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h4>Example: Amortized Queues</h4>
|
|
|
|
<pre><code>
|
|
queue dequeue(queue) {
|
|
if(queue.current != NULL){
|
|
|
|
return { current: pop(queue.current), todo: queue.todo }
|
|
|
|
} else if(queue.todo != NULL) {
|
|
|
|
return { current: reverse(queue.todo), todo: NULL }
|
|
|
|
} else {
|
|
return { current: NULL, todo: NULL }
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p class="fragment">What is the cost?</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h4>Example: Amortized Analysis</h4>
|
|
<dl>
|
|
<dt class="fragment">enqueue(): Push onto todo stack</dt>
|
|
<dd class="fragment">$O(1) + \text{create } 1 \text{ credit}$</dd>
|
|
|
|
<dt class="fragment">dequeue(): Pop current OR Reverse todo </dt>
|
|
<dd class="fragment">Either:<ul>
|
|
<li>Pop current queue: <span class="fragment">$O(1)$</span></li>
|
|
<li>Reverse stack: <span class="fragment">$O(1) + \text{consume } N \text{ credits}$</span></li>
|
|
</ul>
|
|
</dl>
|
|
|
|
<p class="fragment">Critical requirement of amortized analysis: Must ensure that every credit consumed is created.</p>
|
|
</section>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script src="../reveal.js-3.7.0/lib/js/head.min.js"></script>
|
|
<script src="../reveal.js-3.7.0/js/reveal.js"></script>
|
|
|
|
<script>
|
|
|
|
// More info https://github.com/hakimel/reveal.js#configuration
|
|
Reveal.initialize({
|
|
controls: true,
|
|
progress: true,
|
|
history: true,
|
|
center: true,
|
|
|
|
transition: 'slide', // none/fade/slide/convex/concave/zoom
|
|
|
|
// More info https://github.com/hakimel/reveal.js#dependencies
|
|
dependencies: [
|
|
{ src: '../reveal.js-3.7.0/lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
|
{ src: '../reveal.js-3.7.0/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
|
{ src: '../reveal.js-3.7.0/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
|
{ src: '../reveal.js-3.7.0/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
|
|
{ src: '../reveal.js-3.7.0/plugin/search/search.js', async: true },
|
|
{ src: '../reveal.js-3.7.0/plugin/zoom-js/zoom.js', async: true },
|
|
{ src: '../reveal.js-3.7.0/plugin/notes/notes.js', async: true },
|
|
{ src: '../reveal.js-3.7.0/plugin/math/math.js',
|
|
condition: function() { return true; },
|
|
mathjax: '../reveal.js-3.7.0/js/MathJax.js'
|
|
},
|
|
{ src: '../reveal.js-3.7.0/plugin/svginline/es6-promise.auto.js', async: false },
|
|
{ src: '../reveal.js-3.7.0/plugin/svginline/data-src-svg.js', async: false }
|
|
]
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|