1919
2020#define POINTS 32768
2121
22+ /* Default memory limit (64 MB) */
23+ #define DEFAULT_MEM_LIMIT (64 * 1024 * 1024)
24+ /* Select bench algorithm automatically */
25+ #define BENCH_ALGO_AUTO (-1)
26+
2227static void help (char * * argv , int default_iters ) {
2328 printf ("Benchmark EC multiplication algorithms\n" );
2429 printf ("\n" );
@@ -30,23 +35,25 @@ static void help(char **argv, int default_iters) {
3035 printf ("function name. The letter 'g' indicates that one of the points is the generator.\n" );
3136 printf ("The benchmarks are divided by the number of points.\n" );
3237 printf ("\n" );
33- printf ("default (ecmult_multi ): picks pippenger_wnaf or strauss_wnaf depending on the \n" );
34- printf (" batch size \n" );
35- printf ("pippenger_wnaf: for all batch sizes\n" );
36- printf ("strauss_wnaf : for all batch sizes \n" );
37- printf ("simple: multiply and sum each point individually \n" );
38+ printf ("default (auto ): automatically select best algorithm \n" );
39+ printf ("pippenger_wnaf: for all batch sizes \n" );
40+ printf ("strauss_wnaf: for all batch sizes\n" );
41+ printf ("simple : multiply and sum each point individually \n" );
42+ printf ("\n" );
3843}
3944
4045typedef struct {
4146 /* Setup once in advance */
4247 secp256k1_context * ctx ;
43- secp256k1_scratch_space * scratch ;
4448 secp256k1_scalar * scalars ;
4549 secp256k1_ge * pubkeys ;
4650 secp256k1_gej * pubkeys_gej ;
4751 secp256k1_scalar * seckeys ;
4852 secp256k1_gej * expected_output ;
49- secp256k1_ecmult_multi_func ecmult_multi ;
53+
54+ /* Algorithm selection */
55+ int forced_algo ;
56+ size_t mem_limit ;
5057
5158 /* Changes per benchmark */
5259 size_t count ;
@@ -214,32 +221,54 @@ static void run_ecmult_bench(bench_data* data, int iters) {
214221 run_benchmark (str , bench_ecmult_1p_g , bench_ecmult_setup , bench_ecmult_1p_g_teardown , data , 10 , 2 * iters );
215222}
216223
217- static int bench_ecmult_multi_callback (secp256k1_scalar * sc , secp256k1_ge * ge , size_t idx , void * arg ) {
218- bench_data * data = (bench_data * )arg ;
219- if (data -> includes_g ) ++ idx ;
220- if (idx == 0 ) {
221- * sc = data -> scalars [data -> offset1 ];
222- * ge = secp256k1_ge_const_g ;
223- } else {
224- * sc = data -> scalars [(data -> offset1 + idx ) % POINTS ];
225- * ge = data -> pubkeys [(data -> offset2 + idx - 1 ) % POINTS ];
226- }
227- return 1 ;
228- }
229-
230224static void bench_ecmult_multi (void * arg , int iters ) {
231225 bench_data * data = (bench_data * )arg ;
232226
233227 int includes_g = data -> includes_g ;
234228 int iter ;
235229 int count = data -> count ;
230+ size_t n_points = count - includes_g ;
231+ secp256k1_ecmult_multi_algo algo ;
232+ secp256k1_ge * points = NULL ;
233+ secp256k1_scalar * scalars = NULL ;
234+ size_t i ;
236235 iters = iters / data -> count ;
237236
237+ if (n_points > 0 ) {
238+ points = (secp256k1_ge * )malloc (n_points * sizeof (secp256k1_ge ));
239+ scalars = (secp256k1_scalar * )malloc (n_points * sizeof (secp256k1_scalar ));
240+ CHECK (points != NULL );
241+ CHECK (scalars != NULL );
242+ }
243+
238244 for (iter = 0 ; iter < iters ; ++ iter ) {
239- data -> ecmult_multi (& data -> ctx -> error_callback , data -> scratch , & data -> output [iter ], data -> includes_g ? & data -> scalars [data -> offset1 ] : NULL , bench_ecmult_multi_callback , arg , count - includes_g );
245+ const secp256k1_scalar * g_scalar_ptr = NULL ;
246+
247+ if (includes_g ) {
248+ g_scalar_ptr = & data -> scalars [data -> offset1 ];
249+ }
250+
251+ for (i = 0 ; i < n_points ; ++ i ) {
252+ size_t idx = includes_g ? i + 1 : i ;
253+ scalars [i ] = data -> scalars [(data -> offset1 + idx ) % POINTS ];
254+ points [i ] = data -> pubkeys [(data -> offset2 + i ) % POINTS ];
255+ }
256+
257+ if (data -> forced_algo >= 0 ) {
258+ algo = data -> forced_algo ;
259+ } else {
260+ algo = secp256k1_ecmult_multi_select (data -> mem_limit , n_points );
261+ }
262+
263+ CHECK (secp256k1_ecmult_multi_internal (& data -> ctx -> error_callback , algo , & data -> output [iter ],
264+ n_points , points , scalars , g_scalar_ptr ));
265+
240266 data -> offset1 = (data -> offset1 + count ) % POINTS ;
241267 data -> offset2 = (data -> offset2 + count - 1 ) % POINTS ;
242268 }
269+
270+ free (points );
271+ free (scalars );
243272}
244273
245274static void bench_ecmult_multi_setup (void * arg ) {
@@ -309,12 +338,12 @@ static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_
309338int main (int argc , char * * argv ) {
310339 bench_data data ;
311340 int i , p ;
312- size_t scratch_size ;
313341
314342 int default_iters = 10000 ;
315343 int iters = get_iters (default_iters );
316344
317- data .ecmult_multi = secp256k1_ecmult_multi_var ;
345+ data .forced_algo = BENCH_ALGO_AUTO ;
346+ data .mem_limit = DEFAULT_MEM_LIMIT ;
318347
319348 if (argc > 1 ) {
320349 if (have_flag (argc , argv , "-h" )
@@ -324,12 +353,17 @@ int main(int argc, char **argv) {
324353 return EXIT_SUCCESS ;
325354 } else if (have_flag (argc , argv , "pippenger_wnaf" )) {
326355 printf ("Using pippenger_wnaf:\n" );
327- data .ecmult_multi = secp256k1_ecmult_pippenger_batch_single ;
356+ /* TODO: Make this a dynamic selection again */
357+ data .forced_algo = SECP256K1_ECMULT_MULTI_ALGO_PIPPENGER_4 ;
328358 } else if (have_flag (argc , argv , "strauss_wnaf" )) {
329359 printf ("Using strauss_wnaf:\n" );
330- data .ecmult_multi = secp256k1_ecmult_strauss_batch_single ;
360+ data .forced_algo = SECP256K1_ECMULT_MULTI_ALGO_STRAUSS ;
331361 } else if (have_flag (argc , argv , "simple" )) {
332362 printf ("Using simple algorithm:\n" );
363+ data .forced_algo = SECP256K1_ECMULT_MULTI_ALGO_TRIVIAL ;
364+ } else if (have_flag (argc , argv , "auto" )) {
365+ printf ("Using automatic algorithm selection:\n" );
366+ data .forced_algo = BENCH_ALGO_AUTO ;
333367 } else {
334368 fprintf (stderr , "%s: unrecognized argument '%s'.\n\n" , argv [0 ], argv [1 ]);
335369 help (argv , default_iters );
@@ -338,12 +372,6 @@ int main(int argc, char **argv) {
338372 }
339373
340374 data .ctx = secp256k1_context_create (SECP256K1_CONTEXT_NONE );
341- scratch_size = secp256k1_strauss_scratch_size (POINTS ) + STRAUSS_SCRATCH_OBJECTS * ALIGNMENT ;
342- if (!have_flag (argc , argv , "simple" )) {
343- data .scratch = secp256k1_scratch_space_create (data .ctx , scratch_size );
344- } else {
345- data .scratch = NULL ;
346- }
347375
348376 /* Allocate stuff */
349377 data .scalars = malloc (sizeof (secp256k1_scalar ) * POINTS );
@@ -389,9 +417,6 @@ int main(int argc, char **argv) {
389417 printf ("Skipping some benchmarks due to SECP256K1_BENCH_ITERS <= 2\n" );
390418 }
391419
392- if (data .scratch != NULL ) {
393- secp256k1_scratch_space_destroy (data .ctx , data .scratch );
394- }
395420 secp256k1_context_destroy (data .ctx );
396421 free (data .scalars );
397422 free (data .pubkeys );
0 commit comments