1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/Extended8ModExp.html
2025-01-28 10:11:14 +01:00

701 lines
No EOL
47 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>8.7. Extended Example: Parallel Modular Exponentiation &mdash; Computer Systems Fundamentals</title>
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
<style>
.underline { text-decoration: underline; }
</style>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.4.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": {
scale: "80"
}
});
</script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
<link rel="next" title="1. Parallel and Distributed Systems" href="ParallelDistributedOverview.html" />
<link rel="prev" title="6. Cigarette Smokers Problem and the Limits of Semaphores and Locks" href="CigSmokers.html" />
</head><body>
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
<!-- Show a navbar toggler on mobile -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="defaultNavbars">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle jmu-gold rounded" href="Extended8ModExp.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
<a class="dropdown-item" tabindex="-1" href="Extended8ModExp.html#"><b>Chapter 1</b></a>
<a class="dropdown-item" href="IntroConcSysOverview.html">&nbsp;&nbsp;&nbsp;1.1. Introduction to Concurrent Systems</a>
<a class="dropdown-item" href="SysAndModels.html">&nbsp;&nbsp;&nbsp;1.2. Systems and Models</a>
<a class="dropdown-item" href="Themes.html">&nbsp;&nbsp;&nbsp;1.3. Themes and Guiding Principles</a>
<a class="dropdown-item" href="Architectures.html">&nbsp;&nbsp;&nbsp;1.4. System Architectures</a>
<a class="dropdown-item" href="StateModels.html">&nbsp;&nbsp;&nbsp;1.5. State Models in UML</a>
<a class="dropdown-item" href="SequenceModels.html">&nbsp;&nbsp;&nbsp;1.6. Sequence Models in UML</a>
<a class="dropdown-item" href="StateModelImplementation.html">&nbsp;&nbsp;&nbsp;1.7. Extended Example: State Model Implementation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
<a class="dropdown-item" href="ProcessesOverview.html">&nbsp;&nbsp;&nbsp;2.1. Processes and OS Basics</a>
<a class="dropdown-item" href="Multiprogramming.html">&nbsp;&nbsp;&nbsp;2.2. Processes and Multiprogramming</a>
<a class="dropdown-item" href="KernelMechanics.html">&nbsp;&nbsp;&nbsp;2.3. Kernel Mechanics</a>
<a class="dropdown-item" href="Syscall.html">&nbsp;&nbsp;&nbsp;2.4. System Call Interface</a>
<a class="dropdown-item" href="ProcessCycle.html">&nbsp;&nbsp;&nbsp;2.5. Process Life Cycle</a>
<a class="dropdown-item" href="UnixFile.html">&nbsp;&nbsp;&nbsp;2.6. The UNIX File Abstraction</a>
<a class="dropdown-item" href="EventsSignals.html">&nbsp;&nbsp;&nbsp;2.7. Events and Signals</a>
<a class="dropdown-item" href="Extended2Processes.html">&nbsp;&nbsp;&nbsp;2.8. Extended Example: Listing Files with Processes</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
<a class="dropdown-item" href="IPCOverview.html">&nbsp;&nbsp;&nbsp;3.1. Concurrency with IPC</a>
<a class="dropdown-item" href="IPCModels.html">&nbsp;&nbsp;&nbsp;3.2. IPC Models</a>
<a class="dropdown-item" href="Pipes.html">&nbsp;&nbsp;&nbsp;3.3. Pipes and FIFOs</a>
<a class="dropdown-item" href="MMap.html">&nbsp;&nbsp;&nbsp;3.4. Shared Memory With Memory-mapped Files</a>
<a class="dropdown-item" href="POSIXvSysV.html">&nbsp;&nbsp;&nbsp;3.5. POSIX vs. System V IPC</a>
<a class="dropdown-item" href="MQueues.html">&nbsp;&nbsp;&nbsp;3.6. Message Passing With Message Queues</a>
<a class="dropdown-item" href="ShMem.html">&nbsp;&nbsp;&nbsp;3.7. Shared Memory</a>
<a class="dropdown-item" href="IPCSems.html">&nbsp;&nbsp;&nbsp;3.8. Semaphores</a>
<a class="dropdown-item" href="Extended3Bash.html">&nbsp;&nbsp;&nbsp;3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
<a class="dropdown-item" href="SocketsOverview.html">&nbsp;&nbsp;&nbsp;4.1. Networked Concurrency</a>
<a class="dropdown-item" href="FiveLayer.html">&nbsp;&nbsp;&nbsp;4.2. The TCP/IP Internet Model</a>
<a class="dropdown-item" href="NetApps.html">&nbsp;&nbsp;&nbsp;4.3. Network Applications and Protocols</a>
<a class="dropdown-item" href="Sockets.html">&nbsp;&nbsp;&nbsp;4.4. The Socket Interface</a>
<a class="dropdown-item" href="TCPSockets.html">&nbsp;&nbsp;&nbsp;4.5. TCP Socket Programming: HTTP</a>
<a class="dropdown-item" href="UDPSockets.html">&nbsp;&nbsp;&nbsp;4.6. UDP Socket Programming: DNS</a>
<a class="dropdown-item" href="AppBroadcast.html">&nbsp;&nbsp;&nbsp;4.7. Application-Layer Broadcasting: DHCP</a>
<a class="dropdown-item" href="Extended4CGI.html">&nbsp;&nbsp;&nbsp;4.8. Extended Example: CGI Web Server</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
<a class="dropdown-item" href="InternetOverview.html">&nbsp;&nbsp;&nbsp;5.1. The Internet and Connectivity</a>
<a class="dropdown-item" href="AppLayer.html">&nbsp;&nbsp;&nbsp;5.2. Application Layer: Overlay Networks</a>
<a class="dropdown-item" href="TransLayer.html">&nbsp;&nbsp;&nbsp;5.3. Transport Layer</a>
<a class="dropdown-item" href="NetSec.html">&nbsp;&nbsp;&nbsp;5.4. Network Security Fundamentals</a>
<a class="dropdown-item" href="NetLayer.html">&nbsp;&nbsp;&nbsp;5.5. Network Layer: IP</a>
<a class="dropdown-item" href="LinkLayer.html">&nbsp;&nbsp;&nbsp;5.6. Link Layer</a>
<a class="dropdown-item" href="Wireless.html">&nbsp;&nbsp;&nbsp;5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
<a class="dropdown-item" href="Extended5DNS.html">&nbsp;&nbsp;&nbsp;5.8. Extended Example: DNS client</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
<a class="dropdown-item" href="ThreadsOverview.html">&nbsp;&nbsp;&nbsp;6.1. Concurrency with Multithreading</a>
<a class="dropdown-item" href="ProcVThreads.html">&nbsp;&nbsp;&nbsp;6.2. Processes vs. Threads</a>
<a class="dropdown-item" href="RaceConditions.html">&nbsp;&nbsp;&nbsp;6.3. Race Conditions and Critical Sections</a>
<a class="dropdown-item" href="POSIXThreads.html">&nbsp;&nbsp;&nbsp;6.4. POSIX Thread Library</a>
<a class="dropdown-item" href="ThreadArgs.html">&nbsp;&nbsp;&nbsp;6.5. Thread Arguments and Return Values</a>
<a class="dropdown-item" href="ImplicitThreads.html">&nbsp;&nbsp;&nbsp;6.6. Implicit Threading and Language-based Threads</a>
<a class="dropdown-item" href="Extended6Input.html">&nbsp;&nbsp;&nbsp;6.7. Extended Example: Keyboard Input Listener</a>
<a class="dropdown-item" href="Extended6Primes.html">&nbsp;&nbsp;&nbsp;6.8. Extended Example: Concurrent Prime Number Search</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
<a class="dropdown-item" href="SynchOverview.html">&nbsp;&nbsp;&nbsp;7.1. Synchronization Primitives</a>
<a class="dropdown-item" href="CritSect.html">&nbsp;&nbsp;&nbsp;7.2. Critical Sections and Peterson's Solution</a>
<a class="dropdown-item" href="Locks.html">&nbsp;&nbsp;&nbsp;7.3. Locks</a>
<a class="dropdown-item" href="Semaphores.html">&nbsp;&nbsp;&nbsp;7.4. Semaphores</a>
<a class="dropdown-item" href="Barriers.html">&nbsp;&nbsp;&nbsp;7.5. Barriers</a>
<a class="dropdown-item" href="Condvars.html">&nbsp;&nbsp;&nbsp;7.6. Condition Variables</a>
<a class="dropdown-item" href="Deadlock.html">&nbsp;&nbsp;&nbsp;7.7. Deadlock</a>
<a class="dropdown-item" href="Extended7Events.html">&nbsp;&nbsp;&nbsp;7.8. Extended Example: Event Log File</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
<a class="dropdown-item" href="SynchProblemsOverview.html">&nbsp;&nbsp;&nbsp;8.1. Synchronization Patterns and Problems</a>
<a class="dropdown-item" href="SynchDesign.html">&nbsp;&nbsp;&nbsp;8.2. Basic Synchronization Design Patterns</a>
<a class="dropdown-item" href="ProdCons.html">&nbsp;&nbsp;&nbsp;8.3. Producer-Consumer Problem</a>
<a class="dropdown-item" href="ReadWrite.html">&nbsp;&nbsp;&nbsp;8.4. Readers-Writers Problem</a>
<a class="dropdown-item" href="DiningPhil.html">&nbsp;&nbsp;&nbsp;8.5. Dining Philosophers Problem and Deadlock</a>
<a class="dropdown-item" href="CigSmokers.html">&nbsp;&nbsp;&nbsp;8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
<a class="dropdown-item" href="Extended8ModExp.html">&nbsp;&nbsp;&nbsp;8.7. Extended Example: Parallel Modular Exponentiation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
<a class="dropdown-item" href="ParallelDistributedOverview.html">&nbsp;&nbsp;&nbsp;9.1. Parallel and Distributed Systems</a>
<a class="dropdown-item" href="ParVConc.html">&nbsp;&nbsp;&nbsp;9.2. Parallelism vs. Concurrency</a>
<a class="dropdown-item" href="ParallelDesign.html">&nbsp;&nbsp;&nbsp;9.3. Parallel Design Patterns</a>
<a class="dropdown-item" href="Scaling.html">&nbsp;&nbsp;&nbsp;9.4. Limits of Parallelism and Scaling</a>
<a class="dropdown-item" href="DistTiming.html">&nbsp;&nbsp;&nbsp;9.5. Timing in Distributed Environments</a>
<a class="dropdown-item" href="DistDataStorage.html">&nbsp;&nbsp;&nbsp;9.6. Reliable Data Storage and Location</a>
<a class="dropdown-item" href="DistConsensus.html">&nbsp;&nbsp;&nbsp;9.7. Consensus in Distributed Systems</a>
<a class="dropdown-item" href="Extended9Blockchain.html">&nbsp;&nbsp;&nbsp;9.8. Extended Example: Blockchain Proof-of-Work</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Appendix A</b></a>
<a class="dropdown-item" href="CLangOverview.html">&nbsp;&nbsp;&nbsp;A.1. C Language Reintroduction</a>
<a class="dropdown-item" href="Debugging.html">&nbsp;&nbsp;&nbsp;A.2. Documentation and Debugging</a>
<a class="dropdown-item" href="BasicTypes.html">&nbsp;&nbsp;&nbsp;A.3. Basic Types and Pointers</a>
<a class="dropdown-item" href="Arrays.html">&nbsp;&nbsp;&nbsp;A.4. Arrays, Structs, Enums, and Type Definitions</a>
<a class="dropdown-item" href="Functions.html">&nbsp;&nbsp;&nbsp;A.5. Functions and Scope</a>
<a class="dropdown-item" href="Pointers.html">&nbsp;&nbsp;&nbsp;A.6. Pointers and Dynamic Allocation</a>
<a class="dropdown-item" href="Strings.html">&nbsp;&nbsp;&nbsp;A.7. Strings</a>
<a class="dropdown-item" href="FunctionPointers.html">&nbsp;&nbsp;&nbsp;A.8. Function Pointers</a>
<a class="dropdown-item" href="Files.html">&nbsp;&nbsp;&nbsp;A.9. Files</a>
</div>
</li>
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/Extended8ModExp.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="CigSmokers.html">8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="ParallelDistributedOverview.html">9.1. Parallel and Distributed Systems</a>&#160;&#160;»
</div>
<br />
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
<script type="text/javascript" src="_static/js/config.js"></script>
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
<div class="container">
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "Extended8ModExp";ODSA.SETTINGS.MODULE_LONG_NAME = "Extended Example: Parallel Modular Exponentiation";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Patterns and Problems"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:51"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="extended-example-parallel-modular-exponentiation">
<h1>8.7. Extended Example: Parallel Modular Exponentiation<a class="headerlink" href="Extended8ModExp.html#extended-example-parallel-modular-exponentiation" title="Permalink to this headline"></a></h1>
<p>Modular exponentiation is a mathematical calculation that is used in a variety
of applications, including public key cryptography. This operation simply
consists of performing an integer exponentiation and applying a modulus. For
instance, 2<sup>3</sup> mod 7 = 8 mod 7 ≡ 1 mod 7. This parallel form makes
use of the fact that multiplication is associative; if we want to compute
(2<sup>3</sup> * 5<sup>4</sup> ) mod 7, we can calculate
2<sup>3</sup> mod 7 and 5<sup>4</sup> mod 7 in parallel, then multiply
their results together. This form uses an intentionally slow implementation of
modular exponentiation to illustrate the performance improvement from
parallelism.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#include</span> <span class="cpf">&lt;assert.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;inttypes.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;pthread.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;semaphore.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
<span class="kt">uint64_t</span> <span class="nf">mod_power</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="p">,</span> <span class="kt">uint64_t</span><span class="p">);</span>
<span class="kt">void</span> <span class="o">*</span> <span class="nf">mod_power_consumer</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">);</span>
<span class="kt">uint64_t</span> <span class="o">*</span> <span class="nf">randomize_powers</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">,</span> <span class="kt">unsigned</span><span class="p">,</span> <span class="kt">double</span><span class="p">,</span> <span class="kt">size_t</span><span class="p">);</span>
<span class="cm">/* Can use this to change the queue size */</span>
<span class="cp">#define QUEUE_SIZE 10</span>
<span class="cm">/* Synchronization primitives and global result */</span>
<span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span>
<span class="cp">#define SEM_AVAILABLE &quot;/OpenCSF_Available&quot;</span>
<span class="cp">#define SEM_READY &quot;/OpenCSF_Ready&quot;</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">space_available</span><span class="p">;</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">item_ready</span><span class="p">;</span>
<span class="kt">uint64_t</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="cm">/* Each entry is for a single base^power computation */</span>
<span class="k">struct</span> <span class="n">queue_entry</span> <span class="p">{</span>
<span class="kt">uint64_t</span> <span class="n">base</span><span class="p">;</span>
<span class="kt">uint64_t</span> <span class="n">power</span><span class="p">;</span>
<span class="p">};</span>
<span class="cm">/* Variables that define the queue structure */</span>
<span class="k">struct</span> <span class="n">queue_entry</span> <span class="n">queue</span><span class="p">[</span><span class="n">QUEUE_SIZE</span><span class="p">];</span>
<span class="kt">size_t</span> <span class="n">next_out</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">next_in</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="cm">/* Set of 100 primes and the modulus to use for calculations */</span>
<span class="kt">uint64_t</span> <span class="n">primes</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">37</span><span class="p">,</span> <span class="mi">41</span><span class="p">,</span> <span class="mi">43</span><span class="p">,</span> <span class="mi">47</span><span class="p">,</span> <span class="mi">53</span><span class="p">,</span>
<span class="mi">59</span><span class="p">,</span> <span class="mi">61</span><span class="p">,</span> <span class="mi">67</span><span class="p">,</span> <span class="mi">71</span><span class="p">,</span> <span class="mi">73</span><span class="p">,</span> <span class="mi">79</span><span class="p">,</span> <span class="mi">83</span><span class="p">,</span> <span class="mi">89</span><span class="p">,</span> <span class="mi">97</span><span class="p">,</span> <span class="mi">101</span><span class="p">,</span> <span class="mi">103</span><span class="p">,</span> <span class="mi">107</span><span class="p">,</span> <span class="mi">109</span><span class="p">,</span> <span class="mi">113</span><span class="p">,</span>
<span class="mi">127</span><span class="p">,</span> <span class="mi">131</span><span class="p">,</span> <span class="mi">137</span><span class="p">,</span> <span class="mi">139</span><span class="p">,</span> <span class="mi">149</span><span class="p">,</span> <span class="mi">151</span><span class="p">,</span> <span class="mi">157</span><span class="p">,</span> <span class="mi">163</span><span class="p">,</span> <span class="mi">167</span><span class="p">,</span> <span class="mi">173</span><span class="p">,</span> <span class="mi">179</span><span class="p">,</span> <span class="mi">181</span><span class="p">,</span>
<span class="mi">191</span><span class="p">,</span> <span class="mi">193</span><span class="p">,</span> <span class="mi">197</span><span class="p">,</span> <span class="mi">199</span><span class="p">,</span> <span class="mi">211</span><span class="p">,</span> <span class="mi">223</span><span class="p">,</span> <span class="mi">227</span><span class="p">,</span> <span class="mi">229</span><span class="p">,</span> <span class="mi">233</span><span class="p">,</span> <span class="mi">239</span><span class="p">,</span> <span class="mi">241</span><span class="p">,</span> <span class="mi">251</span><span class="p">,</span>
<span class="mi">257</span><span class="p">,</span> <span class="mi">263</span><span class="p">,</span> <span class="mi">269</span><span class="p">,</span> <span class="mi">271</span><span class="p">,</span> <span class="mi">277</span><span class="p">,</span> <span class="mi">281</span><span class="p">,</span> <span class="mi">283</span><span class="p">,</span> <span class="mi">293</span><span class="p">,</span> <span class="mi">307</span><span class="p">,</span> <span class="mi">311</span><span class="p">,</span> <span class="mi">313</span><span class="p">,</span> <span class="mi">317</span><span class="p">,</span>
<span class="mi">331</span><span class="p">,</span> <span class="mi">337</span><span class="p">,</span> <span class="mi">347</span><span class="p">,</span> <span class="mi">349</span><span class="p">,</span> <span class="mi">353</span><span class="p">,</span> <span class="mi">359</span><span class="p">,</span> <span class="mi">367</span><span class="p">,</span> <span class="mi">373</span><span class="p">,</span> <span class="mi">379</span><span class="p">,</span> <span class="mi">383</span><span class="p">,</span> <span class="mi">389</span><span class="p">,</span> <span class="mi">397</span><span class="p">,</span>
<span class="mi">401</span><span class="p">,</span> <span class="mi">409</span><span class="p">,</span> <span class="mi">419</span><span class="p">,</span> <span class="mi">421</span><span class="p">,</span> <span class="mi">431</span><span class="p">,</span> <span class="mi">433</span><span class="p">,</span> <span class="mi">439</span><span class="p">,</span> <span class="mi">443</span><span class="p">,</span> <span class="mi">449</span><span class="p">,</span> <span class="mi">457</span><span class="p">,</span> <span class="mi">461</span><span class="p">,</span> <span class="mi">463</span><span class="p">,</span>
<span class="mi">467</span><span class="p">,</span> <span class="mi">479</span><span class="p">,</span> <span class="mi">487</span><span class="p">,</span> <span class="mi">491</span><span class="p">,</span> <span class="mi">499</span><span class="p">,</span> <span class="mi">503</span><span class="p">,</span> <span class="mi">509</span><span class="p">,</span> <span class="mi">521</span><span class="p">,</span> <span class="mi">523</span><span class="p">,</span> <span class="mi">541</span>
<span class="p">};</span>
<span class="kt">size_t</span> <span class="n">primes_length</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="kt">uint64_t</span> <span class="n">modulus</span> <span class="o">=</span> <span class="mi">524287</span><span class="p">;</span>
<span class="kt">int</span>
<span class="nf">main</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Change these numbers as desired. This set will create 4</span>
<span class="cm"> threads to multiple 50% of the primes, each to a power of</span>
<span class="cm"> at least 10,000. */</span>
<span class="kt">size_t</span> <span class="n">number_of_threads</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">25</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">threshold</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">minimum</span> <span class="o">=</span> <span class="mi">10000000</span><span class="p">;</span>
<span class="cm">/* Generate an array of random powers to use */</span>
<span class="kt">uint64_t</span> <span class="o">*</span><span class="n">powers</span> <span class="o">=</span>
<span class="n">randomize_powers</span> <span class="p">(</span><span class="n">primes_length</span><span class="p">,</span> <span class="n">seed</span><span class="p">,</span> <span class="n">threshold</span><span class="p">,</span> <span class="n">minimum</span><span class="p">);</span>
<span class="cm">/* Initialize synchronization primitives as needed */</span>
<span class="n">pthread_mutex_init</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">sem_unlink</span> <span class="p">(</span><span class="n">SEM_AVAILABLE</span><span class="p">);</span> <span class="c1">// Delete an old semaphore instance</span>
<span class="n">sem_unlink</span> <span class="p">(</span><span class="n">SEM_READY</span><span class="p">);</span> <span class="c1">// Delete an old semaphore instance</span>
<span class="n">space_available</span> <span class="o">=</span>
<span class="n">sem_open</span> <span class="p">(</span><span class="n">SEM_AVAILABLE</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_EXCL</span><span class="p">,</span> <span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span><span class="p">,</span> <span class="n">QUEUE_SIZE</span><span class="p">);</span>
<span class="n">item_ready</span> <span class="o">=</span> <span class="n">sem_open</span> <span class="p">(</span><span class="n">SEM_READY</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_EXCL</span><span class="p">,</span> <span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="cm">/* Create the pool of worker threads; each will */</span>
<span class="n">pthread_t</span> <span class="n">threads</span><span class="p">[</span><span class="n">number_of_threads</span><span class="p">];</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">threads</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">threads</span><span class="p">));</span>
<span class="kt">size_t</span> <span class="n">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">number_of_threads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">pthread_create</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">mod_power_consumer</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Producer side of the producer/consumer. Select a pair</span>
<span class="cm"> of prime/power and add the entry to the queue. */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">primes_length</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">queue_entry</span> <span class="n">entry</span><span class="p">;</span>
<span class="n">entry</span><span class="p">.</span><span class="n">base</span> <span class="o">=</span> <span class="n">primes</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="n">entry</span><span class="p">.</span><span class="n">power</span> <span class="o">=</span> <span class="n">powers</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="cm">/* Wait until space is ready */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">space_available</span><span class="p">);</span>
<span class="n">queue</span><span class="p">[</span><span class="n">next_in</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry</span><span class="p">;</span>
<span class="n">next_in</span> <span class="o">=</span> <span class="p">(</span><span class="n">next_in</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">QUEUE_SIZE</span><span class="p">;</span>
<span class="cm">/* Signal that an item was added */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">item_ready</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* No more powers needed from the array */</span>
<span class="n">free</span> <span class="p">(</span><span class="n">powers</span><span class="p">);</span>
<span class="n">powers</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="cm">/* Now start filling the queue with -1 values to terminate</span>
<span class="cm"> the helper threads */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">number_of_threads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">queue_entry</span> <span class="n">blank</span><span class="p">;</span>
<span class="n">blank</span><span class="p">.</span><span class="n">base</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="n">blank</span><span class="p">.</span><span class="n">power</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="cm">/* Wait for space */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">space_available</span><span class="p">);</span>
<span class="n">queue</span><span class="p">[</span><span class="n">next_in</span><span class="p">]</span> <span class="o">=</span> <span class="n">blank</span><span class="p">;</span>
<span class="n">next_in</span> <span class="o">=</span> <span class="p">(</span><span class="n">next_in</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">QUEUE_SIZE</span><span class="p">;</span>
<span class="cm">/* Signal that an item was added */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">item_ready</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Join all of the threads when finished */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">number_of_threads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">pthread_join</span> <span class="p">(</span><span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Clean up all synchronization primitives */</span>
<span class="n">pthread_mutex_destroy</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>
<span class="n">sem_close</span> <span class="p">(</span><span class="n">item_ready</span><span class="p">);</span>
<span class="n">sem_close</span> <span class="p">(</span><span class="n">space_available</span><span class="p">);</span>
<span class="n">sem_unlink</span> <span class="p">(</span><span class="n">SEM_AVAILABLE</span><span class="p">);</span>
<span class="n">sem_unlink</span> <span class="p">(</span><span class="n">SEM_READY</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Product is %&quot;</span> <span class="n">PRIu64</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
<span class="k">return</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Consumer thread. Each thread runs until it receives a</span>
<span class="cm"> power of -1 (indicating finished). After a base/power</span>
<span class="cm"> pair is pulled from the queue, the thread will compute</span>
<span class="cm"> base^power mod modulus, then multiple that by the global</span>
<span class="cm"> result product. */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">mod_power_consumer</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">queue_entry</span> <span class="n">entry</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Consumer side waits until an item is ready */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">item_ready</span><span class="p">);</span>
<span class="cm">/* Multiple consumers, so lock the queue */</span>
<span class="n">pthread_mutex_lock</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>
<span class="n">entry</span> <span class="o">=</span> <span class="n">queue</span><span class="p">[</span><span class="n">next_out</span><span class="p">];</span>
<span class="n">next_out</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">next_out</span> <span class="o">%=</span> <span class="n">QUEUE_SIZE</span><span class="p">;</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>
<span class="cm">/* Let producer no there&#39;s at least one space */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">space_available</span><span class="p">);</span>
<span class="cm">/* Check for termination signal */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="n">power</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
<span class="cm">/* Computer base^power, then multiple result with</span>
<span class="cm"> the global product */</span>
<span class="kt">uint64_t</span> <span class="n">modp</span> <span class="o">=</span> <span class="n">mod_power</span> <span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="n">base</span><span class="p">,</span> <span class="n">entry</span><span class="p">.</span><span class="n">power</span><span class="p">);</span>
<span class="n">pthread_mutex_lock</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="n">power</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;%&quot;</span> <span class="n">PRIu64</span> <span class="s">&quot; ^ %&quot;</span> <span class="n">PRIu64</span> <span class="s">&quot; mod %&quot;</span> <span class="n">PRIu64</span> <span class="s">&quot; = %&quot;</span> <span class="n">PRIu64</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span>
<span class="n">entry</span><span class="p">.</span><span class="n">base</span><span class="p">,</span> <span class="n">entry</span><span class="p">.</span><span class="n">power</span><span class="p">,</span> <span class="n">modulus</span><span class="p">,</span> <span class="n">modp</span><span class="p">);</span>
<span class="n">result</span> <span class="o">*=</span> <span class="n">modp</span><span class="p">;</span>
<span class="n">result</span> <span class="o">%=</span> <span class="n">modulus</span><span class="p">;</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Intentionally slow mod power routine. Computes</span>
<span class="cm"> base^power mod modulus by multiplying a running</span>
<span class="cm"> product repeatedly by the base. Slow enough to</span>
<span class="cm"> see a speedup from parallel executions. */</span>
<span class="kt">uint64_t</span>
<span class="nf">mod_power</span> <span class="p">(</span><span class="kt">uint64_t</span> <span class="n">base</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">power</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">uint64_t</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">uint64_t</span> <span class="n">product</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">index</span> <span class="o">&lt;</span> <span class="n">power</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">product</span> <span class="o">*=</span> <span class="n">base</span><span class="p">;</span>
<span class="n">product</span> <span class="o">%=</span> <span class="n">modulus</span><span class="p">;</span>
<span class="n">index</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">product</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Create an array of random powers for the primes.</span>
<span class="cm"> The threshold parameter determines (approximately)</span>
<span class="cm"> what percentage of these powers are non-zero. */</span>
<span class="kt">uint64_t</span> <span class="o">*</span>
<span class="nf">randomize_powers</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">length</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">seed</span><span class="p">,</span>
<span class="kt">double</span> <span class="n">threshold</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">minimum</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">size_t</span> <span class="n">i</span><span class="p">;</span>
<span class="kt">uint64_t</span> <span class="o">*</span><span class="n">pows</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="n">length</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="p">));</span>
<span class="n">srand</span> <span class="p">(</span><span class="n">seed</span><span class="p">);</span>
<span class="kt">size_t</span> <span class="n">randoms</span> <span class="o">=</span> <span class="n">length</span> <span class="o">*</span> <span class="n">threshold</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">randoms</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">size_t</span> <span class="n">index</span> <span class="o">=</span> <span class="n">rand</span> <span class="p">()</span> <span class="o">%</span> <span class="n">length</span><span class="p">;</span>
<span class="n">pows</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">rand</span> <span class="p">()</span> <span class="o">%</span> <span class="mi">10</span><span class="p">)</span> <span class="o">*</span> <span class="n">minimum</span><span class="p">;</span>
<span class="n">pows</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">+=</span> <span class="n">rand</span> <span class="p">()</span> <span class="o">%</span> <span class="n">minimum</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">pows</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="CigSmokers.html">8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="ParallelDistributedOverview.html">9.1. Parallel and Distributed Systems</a>&#160;&#160;»
</div>
</div>
<br />
<div class="row jmu-dark-purple-bg">
<div class="col-md-12">
<center>
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
</center>
</div>
</div>
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>