/usr/share/doc/libntl-dev/NTL/tour-ex7.html is in libntl-dev 9.9.1-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | <html>
<head>
<title>
A Tour of NTL: Examples: Thread Pools</title>
</head>
<center>
<a href="tour-ex6.html"><img src="arrow1.gif" alt="[Previous]" align=bottom></a>
<a href="tour-examples.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a>
<img src="arrow3.gif" alt="[Next]" align=bottom>
</center>
<h1>
<p align=center>
A Tour of NTL: Examples: Thread Pools
</p>
</h1>
<p> <hr> <p>
If you have built NTL with <tt>NTL_THREAD_BOOST=on</tt>,
then not only is NTL thread safe, but certain parts
of NTL are designed to use multiple threads to speed things
up.
To implement this, NTL makes use of a <i>thread pool</i>,
which is a collection of threads that are created once
and then used over and over again, to avoid the significant
overhead of thread creation and destruction.
You can also use this same thread pool to speed up
NTL client code.
<p>
To use this feature, you have to include the header file
<tt>NTL/BasicThreadPool.h</tt>.
In your main program, you should also indicate how many threads
you want in the pool.
If you want, say, 8 threads, you so this by calling the function
<tt>SetNumThreads(8)</tt>.
<p>
If you do this, then certain parts of NTL will use these
threads when possible (this is a working in progress).
To use these threads in your own code, the easiest way
to do this is with a <i>parallel for loop</i>,
illustrated in the following example.
See <a href="BasicThreadPool.cpp.html"><tt>BasicThreadPool.txt</tt></a>
for more details.
Consider the following routine:
<!-- STARTPLAIN
void mul(ZZ *x, const ZZ *a, const ZZ *b, long n)
{
for (long i = 0; i < n; i++)
mul(x[i], a[i], b[i]);
}
ENDPLAIN -->
<!-- STARTPRETTY {{{ -->
<p><p><table cellPadding=10px><tr><td><font color="#000000"><font face="monospace">
<font color="#008b00"><b>void</b></font> mul(ZZ *x, <font color="#008b00"><b>const</b></font> ZZ *a, <font color="#008b00"><b>const</b></font> ZZ *b, <font color="#008b00"><b>long</b></font> n) <br>
{<br>
<font color="#b02f60"><b>for</b></font> (<font color="#008b00"><b>long</b></font> i = <font color="#ff8b00">0</font>; i < n; i++)<br>
mul(x[i], a[i], b[i]);<br>
}<br>
</font></font></td></tr></table><p><p>
<!-- }}} ENDPRETTY -->
<p>
We can parallelize it as follows:
<!-- STARTPLAIN
void mul(ZZ *x, const ZZ *a, const ZZ *b, long n)
{
NTL_EXEC_RANGE(n, first, last)
for (long i = first; i < last; i++)
mul(x[i], a[i], b[i]);
NTL_EXEC_RANGE_END
}
ENDPLAIN -->
<!-- STARTPRETTY {{{ -->
<p><p><table cellPadding=10px><tr><td><font color="#000000"><font face="monospace">
<font color="#008b00"><b>void</b></font> mul(ZZ *x, <font color="#008b00"><b>const</b></font> ZZ *a, <font color="#008b00"><b>const</b></font> ZZ *b, <font color="#008b00"><b>long</b></font> n) <br>
{<br>
NTL_EXEC_RANGE(n, first, last) <br>
<br>
<font color="#b02f60"><b>for</b></font> (<font color="#008b00"><b>long</b></font> i = first; i < last; i++)<br>
mul(x[i], a[i], b[i]);<br>
<br>
NTL_EXEC_RANGE_END<br>
}<br>
</font></font></td></tr></table><p><p>
<!-- }}} ENDPRETTY -->
<p>
<tt>NTL_EXEC_RANGE</tt> and
<tt>NTL_EXEC_RANGE_END</tt> are macros that just <i>do the right
thing</i>. If there are <i>nt</i> threads available, the interval
[0..<i>n</i>) will be
partitioned into (up to) <i>nt</i> subintervals, and a different thread will be
used to process each subinterval. You still have to write the for loop
yourself: the macro just declares and initializes variables <i>first</i> and
<i>last</i> (or whatever you want to call them) of type <tt>long</tt>
that represent the
subinterval [<i>first</i>..<i>last</i>) to be processed by one thread.
<p>
Note that the current thread participates as one of the <i>nt</i> available
threads, and that the current thread will wait for all participating threads
to finish their task before proceeding.
<p>
Withing the "body" of this construct, you can freely reference any variables
that are visible at this point. This is implemented using the C++ lambda
feature (capturing all variables by reference).
<p>
This construct will still work even if threads are disabled, in which case
it runs single-threaded with <i>first=0</i> and <i>last=n</i>.
<p>
Note that the code within the <tt>EXEC_RANGE</tt>
body could call other routines that
themselves attempt to execute an <tt>EXEC_RANGE</tt>:
if this happens, the latter
<tt>EXEC_RANGE</tt> will detect this and run single-threaded.
<p>
You may wish to do other things within the <tt>EXEC_RANGE</tt>
body than just execute
a loop. One thing you may want to do is to declare variables. Another
thing you may want to do is setup a local context
for a <tt>ZZ_p</tt> modulus (or
other type of modulus).
Here is an example of doing this:
<!-- STARTPLAIN
void mul(ZZ_p *x, const ZZ_p *a, const ZZ_p *b, long n)
{
ZZ_pContext context;
context.save();
NTL_EXEC_RANGE(n, first, last)
context.restore();
for (long i = first; i < last; i++)
mul(x[i], a[i], b[i]);
NTL_EXEC_RANGE_END
}
ENDPLAIN -->
<!-- STARTPRETTY {{{ -->
<p><p><table cellPadding=10px><tr><td><font color="#000000"><font face="monospace">
<font color="#008b00"><b>void</b></font> mul(ZZ_p *x, <font color="#008b00"><b>const</b></font> ZZ_p *a, <font color="#008b00"><b>const</b></font> ZZ_p *b, <font color="#008b00"><b>long</b></font> n) <br>
{<br>
ZZ_pContext context;<br>
context.save();<br>
<br>
NTL_EXEC_RANGE(n, first, last) <br>
<br>
context.restore();<br>
<br>
<font color="#b02f60"><b>for</b></font> (<font color="#008b00"><b>long</b></font> i = first; i < last; i++)<br>
mul(x[i], a[i], b[i]);<br>
<br>
NTL_EXEC_RANGE_END<br>
}<br>
</font></font></td></tr></table><p><p>
<!-- }}} ENDPRETTY -->
<p>
A lower-level set of tools is available, which allow for
more fine-grained control.
See <a href="BasicThreadPool.cpp.html">BasicThreadPool.txt</a>
for more details.
<center>
<a href="tour-ex6.html"><img src="arrow1.gif" alt="[Previous]" align=bottom></a>
<a href="tour-examples.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a>
<img src="arrow3.gif" alt="[Next]" align=bottom>
</center>
</body>
</html>
|