def test_gmpy2_parallelism_is_safe(self): cpus = cpu_count() problem_size = 1000 secret_keys = Nonces(int_to_q_unchecked(3))[ 0:problem_size] # list of 1000 might-as-well-be-random Q's log_info( f"testing GMPY2 powmod parallelism safety (cpus = {cpus}, problem_size = {problem_size})" ) # compute in parallel start = timer() p = Pool(cpus) keypairs = p.map(elgamal_keypair_from_secret, secret_keys) end1 = timer() # verify scalar for keypair in keypairs: self.assertEqual( keypair.public_key, elgamal_keypair_from_secret(keypair.secret_key).public_key, ) end2 = timer() p.close( ) # apparently necessary to avoid warnings from the Pool system log_info(f"Parallelism speedup: {(end2 - end1) / (end1 - start):.3f}")
def test_gmpy2_parallelism_is_safe(self): """ Ensures running lots of parallel exponentiations still yields the correct answer. This verifies that nothing incorrect is happening in the GMPY2 library """ # Arrange scheduler = Scheduler() problem_size = 1000 random_secret_keys = Nonces(int_to_q_unchecked(3))[0:problem_size] log_info( f"testing GMPY2 powmod parallelism safety (cpus = {scheduler.cpu_count}, problem_size = {problem_size})" ) # Act start = timer() keypairs = scheduler.schedule( elgamal_keypair_from_secret, [list([secret_key]) for secret_key in random_secret_keys], ) end1 = timer() # Assert for keypair in keypairs: self.assertEqual( keypair.public_key, elgamal_keypair_from_secret(keypair.secret_key).public_key, ) end2 = timer() scheduler.close() log_info(f"Parallelism speedup: {(end2 - end1) / (end1 - start):.3f}")
def log_and_print(s: str, verbose: bool = True) -> None: """ Given the string, feeds it to `log_info` and, if `verbose` is True (by default, it is), also prints the string to stdout. """ if verbose: # pragma: no cover print(f" {s}") log_info(s)
def test_log_methods(self): # Arrange message = "test log message" # Act log_debug(message) log_error(message) log_info(message) log_warning(message)
def test_log_methods(self): # Arrange message = "test log message" # Act log_debug(message) log_error(message) log_info(message) log_warning(message) # Assert self.assertIsNotNone(message)
def run_bench(filename: str, pool: Pool, file_dir: Optional[str]) -> None: start_time = timer() print(f"Benchmarking: {filename}") log_info(f"Benchmarking: {filename}") cvrs = read_dominion_csv(filename) if cvrs is None: print(f"Failed to read {filename}, terminating.") exit(1) rows, cols = cvrs.data.shape parse_time = timer() print(f" Parse time: {parse_time - start_time: .3f} sec") assert rows > 0, "can't have zero ballots!" # doesn't matter what the key is, so long as it's consistent for both runs keypair = get_optional(elgamal_keypair_from_secret(int_to_q_unchecked(31337))) tally_start = timer() tally = fast_tally_everything( cvrs, pool, verbose=True, secret_key=keypair.secret_key ) if file_dir: write_fast_tally(tally, file_dir + "_fast") tally_end = timer() assert tally.all_proofs_valid(verbose=True), "proof failure!" print(f"\nstarting ray.io parallelism") rtally_start = timer() rtally = ray_tally_everything( cvrs, secret_key=keypair.secret_key, root_dir=file_dir + "_ray" if file_dir else None, ) rtally_end = timer() if file_dir: rtally_as_fast = rtally.to_fast_tally() assert rtally_as_fast.all_proofs_valid(verbose=True), "proof failure!" assert tally.equivalent( rtally_as_fast, keypair, pool ), "tallies aren't equivalent!" # Note: tally.equivalent() isn't quite as stringent as asserting that absolutely # everything is identical, but it's a pretty good sanity check for our purposes. # In tests/test_ray_tally.py, test_ray_and_multiprocessing_agree goes the extra # distance to create identical tallies from each system and assert their equality. print(f"\nOVERALL PERFORMANCE") print(f" Pool time: {tally_end - tally_start: .3f} sec") print(f" Pool rate: {rows / (tally_end - tally_start): .3f} ballots/sec") print(f" Ray time: {rtally_end - rtally_start : .3f} sec") print(f" Ray rate: {rows / (rtally_end - rtally_start): .3f} ballots/sec") print( f" Ray speedup: {(tally_end - tally_start) / (rtally_end - rtally_start) : .3f} (>1.0 = ray is faster, <1.0 = ray is slower)" ) if file_dir is not None: shutil.rmtree(file_dir + "_ray", ignore_errors=True) shutil.rmtree(file_dir + "_fast", ignore_errors=True)