9
9
* See the License for the specific language governing permissions and
10
10
* limitations under the License. See accompanying LICENSE file.
11
11
*/
12
+
13
+ /* Copyright (C) 2022 Intel Corporation
14
+ * SPDX-License-Identifier: Apache-2.0
15
+ *
16
+ * Modifying HElib to optimize the 01 map.
17
+ * Contributions include
18
+ * Modified:
19
+ * mapTo01
20
+ * added parallelism to existing logic for norm calculation
21
+ * added alternative logic for norm calculation which uses log(d)
22
+ * automorphisms on a single core
23
+ * added an additional optional argument `multithread` which determines
24
+ * which version to run
25
+ *
26
+ */
12
27
/* *
13
28
* @file eqtesting.cpp
14
29
* @brief Useful functions for equality testing...
17
32
#include < helib/timing.h>
18
33
#include < helib/EncryptedArray.h>
19
34
#include < helib/Ptxt.h>
35
+ #include < NTL/BasicThreadPool.h>
20
36
21
37
#include < cstdio>
22
38
@@ -29,24 +45,47 @@ namespace helib {
29
45
// and then outputting y * y^p * ... * y^{p^{d-1}}, with exponentiation to
30
46
// powers of p done via Frobenius.
31
47
32
- // FIXME: the computation of the "norm" y * y^p * ... * y^{p^{d-1}}
33
- // can be done using O(log d) automorphisms, rather than O(d).
34
-
35
- void mapTo01 (const EncryptedArray& ea, Ctxt& ctxt)
48
+ void mapTo01 (const EncryptedArray& ea, Ctxt& ctxt, bool multithread)
36
49
{
37
50
long p = ctxt.getPtxtSpace ();
38
51
if (p != ea.getPAlgebra ().getP ()) // ptxt space is p^r for r>1
39
52
throw LogicError (" mapTo01 not implemented for r>1" );
40
53
41
54
if (p > 2 )
42
55
ctxt.power (p - 1 ); // set y = x^{p-1}
43
-
44
56
long d = ea.getDegree ();
45
- if (d > 1 ) { // compute the product of the d automorphisms
46
- std::vector<Ctxt> v (d, ctxt);
47
- for (long i = 1 ; i < d; i++)
48
- v[i].frobeniusAutomorph (i);
49
- totalProduct (ctxt, v);
57
+ // TODO: investigate this trade off more thoroughly
58
+ // Computing in parallel over t threads has runtime approximately
59
+ // (d - 1)/t, whereas single thread has runtime approx log(d)
60
+ if ((NTL::AvailableThreads () > 1 ) && multithread) {
61
+ // Compute O(d) Frobenius automorphisms in parallel
62
+ if (d > 1 ) {
63
+ // compute the d - 1 automorphisms in parallel
64
+ std::vector<Ctxt> v (d, ctxt);
65
+ NTL_EXEC_RANGE (d - 1 , first, last)
66
+ for (long i = first; i < last; i++)
67
+ v[i + 1 ].frobeniusAutomorph (i + 1 );
68
+ NTL_EXEC_RANGE_END
69
+ // and compute the product of the d automorphisms
70
+ totalProduct (ctxt, v);
71
+ }
72
+ } else {
73
+ // Compute of the "norm" y * y^p * ... * y^{p^{d-1}}
74
+ // using O(log d) automorphisms, rather than O(d).
75
+ long e = 1 ;
76
+ long b = NTL::NumBits (d);
77
+ Ctxt orig = ctxt;
78
+ for (long i = b - 2 ; i >= 0 ; i--) {
79
+ Ctxt tmp = ctxt;
80
+ tmp.frobeniusAutomorph (e);
81
+ ctxt *= tmp;
82
+ e *= 2 ;
83
+ if (NTL::bit (d, i)) {
84
+ ctxt.frobeniusAutomorph (1 );
85
+ ctxt *= orig;
86
+ e++;
87
+ }
88
+ }
50
89
}
51
90
}
52
91
0 commit comments