diff --git a/aad_coin_miner_cpu.c b/aad_coin_miner_cpu.c index 07b9d00..7bfcb3f 100644 --- a/aad_coin_miner_cpu.c +++ b/aad_coin_miner_cpu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aad_data_types.h" #include "aad_utilities.h" #include "aad_sha1_cpu.h" @@ -41,7 +42,7 @@ static double get_wall_time(void) // // mine DETI coins using the CPU (no SIMD) // -static void mine_coins_cpu(u64_t max_attempts) +static void mine_coins_cpu(u64_t max_attempts, double max_time) { u32_t coin[14]; u32_t hash[5]; @@ -75,12 +76,30 @@ static void mine_coins_cpu(u64_t max_attempts) ((u08_t *)coin)[i ^ 3] = 'A' + (i - 12) % 26; printf("Mining DETI coins using CPU (no SIMD)...\n"); + if(max_attempts > 0 && max_time > 0) + printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n", + (unsigned long long)max_attempts, max_time); + else if(max_attempts > 0) + printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts); + else if(max_time > 0) + printf("Will stop after %.2f seconds\n", max_time); + else + printf("Running indefinitely until Ctrl+C...\n"); + printf("Press Ctrl+C to stop\n\n"); double start_time = get_wall_time(); - while(keep_running && (max_attempts == 0 || attempts < max_attempts)) + while(keep_running) { + // Check stopping conditions + if(max_attempts > 0 && attempts >= max_attempts) + break; + + double elapsed = get_wall_time() - start_time; + if(max_time > 0 && elapsed >= max_time) + break; + // Compute SHA1 hash sha1(coin, hash); attempts++; @@ -123,7 +142,7 @@ static void mine_coins_cpu(u64_t max_attempts) // Print progress every 1M attempts if(attempts % 1000000 == 0) { - double elapsed = get_wall_time() - start_time; + elapsed = get_wall_time() - start_time; double rate = attempts / elapsed; printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n", (unsigned long long)attempts, rate / 1e6, coins_found, elapsed); @@ -142,25 +161,50 @@ static void mine_coins_cpu(u64_t max_attempts) save_coin(NULL); } +void print_usage(const char *prog_name) +{ + printf("Usage: %s [OPTIONS]\n", prog_name); + printf("Options:\n"); + printf(" -a Maximum number of attempts\n"); + printf(" -t Maximum time in seconds\n"); + printf(" -h Show this help message\n"); + printf("\nExamples:\n"); + printf(" %s -a 1000000 # Run for 1M attempts\n", prog_name); + printf(" %s -t 60 # Run for 60 seconds\n", prog_name); + printf(" %s -a 1000000 -t 60 # Stop at 1M attempts OR 60s (whichever first)\n", prog_name); + printf(" %s # Run indefinitely until Ctrl+C\n", prog_name); +} + int main(int argc, char *argv[]) { u64_t max_attempts = 0; + double max_time = 0; + int opt; // Set up signal handler for graceful shutdown signal(SIGINT, signal_handler); - if(argc > 1) + // Parse command line options + while((opt = getopt(argc, argv, "a:t:h")) != -1) { - max_attempts = strtoull(argv[1], NULL, 10); - printf("Will perform %llu attempts\n", (unsigned long long)max_attempts); - } - else - { - printf("Usage: %s [max_attempts]\n", argv[0]); - printf("Running indefinitely until Ctrl+C...\n"); + switch(opt) + { + case 'a': + max_attempts = strtoull(optarg, NULL, 10); + break; + case 't': + max_time = atof(optarg); + break; + case 'h': + print_usage(argv[0]); + return 0; + default: + print_usage(argv[0]); + return 1; + } } - mine_coins_cpu(max_attempts); + mine_coins_cpu(max_attempts, max_time); return 0; } diff --git a/aad_coin_miner_cuda.c b/aad_coin_miner_cuda.c index bbd4bfd..672de15 100644 --- a/aad_coin_miner_cuda.c +++ b/aad_coin_miner_cuda.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aad_data_types.h" #include "aad_utilities.h" #include "aad_sha1_cpu.h" @@ -26,6 +27,13 @@ void signal_handler(int signum) keep_running = 0; } +// Get current wall time in seconds +static double get_wall_time(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (double)ts.tv_sec + (double)ts.tv_nsec * 1.0e-9; +} // Coin reconstruction from stored data static void reconstruct_coin(u32_t *stored_data, u32_t coin[14]) @@ -38,7 +46,7 @@ static void reconstruct_coin(u32_t *stored_data, u32_t coin[14]) // // Mine DETI coins using CUDA // -static void mine_coins_cuda(u64_t max_attempts) +static void mine_coins_cuda(u64_t max_attempts, double max_time) { cuda_data_t cd; u32_t *host_storage; @@ -67,15 +75,35 @@ static void mine_coins_cuda(u64_t max_attempts) printf("Grid: %u blocks × %u threads = %u total threads\n", cd.grid_dim_x, cd.block_dim_x, n_threads); printf("Kernel: %s\n", cd.kernel_name); + + if(max_attempts > 0 && max_time > 0) + printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n", + (unsigned long long)max_attempts, max_time); + else if(max_attempts > 0) + printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts); + else if(max_time > 0) + printf("Will stop after %.2f seconds\n", max_time); + else + printf("Running indefinitely until Ctrl+C...\n"); + printf("Press Ctrl+C to stop\n\n"); u64_t base_nonce = 0; u32_t attempts_per_thread = 1024 * 8; // Increased attempts per thread + double start_time = get_wall_time(); time_measurement(); - while(keep_running && (max_attempts == 0 || attempts < max_attempts)) + while(keep_running) { + // Check stopping conditions + if(max_attempts > 0 && attempts >= max_attempts) + break; + + double elapsed = get_wall_time() - start_time; + if(max_time > 0 && elapsed >= max_time) + break; + // Initialize storage area host_storage[0] = 1u; // First unused index @@ -130,24 +158,55 @@ static void mine_coins_cuda(u64_t max_attempts) printf("Coins found: %u\n", coins_found); printf("Kernel launches: %u\n", kernel_runs); - // Save any remaining coins save_coin(NULL); terminate_cuda(&cd); } +void print_usage(const char *prog_name) +{ + printf("Usage: %s [OPTIONS]\n", prog_name); + printf("Options:\n"); + printf(" -a Maximum number of attempts\n"); + printf(" -t Maximum time in seconds\n"); + printf(" -h Show this help message\n"); + printf("\nExamples:\n"); + printf(" %s -a 1000000000 # Run for 1B attempts\n", prog_name); + printf(" %s -t 60 # Run for 60 seconds\n", prog_name); + printf(" %s -a 1000000000 -t 60 # Stop at 1B attempts OR 60s (whichever first)\n", prog_name); + printf(" %s # Run indefinitely until Ctrl+C\n", prog_name); +} + int main(int argc, char *argv[]) { u64_t max_attempts = 0; + double max_time = 0; + int opt; signal(SIGINT, signal_handler); - if(argc > 1) - max_attempts = strtoull(argv[1], NULL, 10); + // Parse command line options + while((opt = getopt(argc, argv, "a:t:h")) != -1) + { + switch(opt) + { + case 'a': + max_attempts = strtoull(optarg, NULL, 10); + break; + case 't': + max_time = atof(optarg); + break; + case 'h': + print_usage(argv[0]); + return 0; + default: + print_usage(argv[0]); + return 1; + } + } - mine_coins_cuda(max_attempts); + mine_coins_cuda(max_attempts, max_time); return 0; } - diff --git a/aad_coin_miner_ocl.c b/aad_coin_miner_ocl.c index e4b5043..faf7d7e 100644 --- a/aad_coin_miner_ocl.c +++ b/aad_coin_miner_ocl.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aad_data_types.h" #include "aad_utilities.h" #include "aad_sha1_cpu.h" @@ -43,7 +44,7 @@ static double get_wall_time(void) // // Mine DETI coins using OpenCL // -static void mine_coins_ocl(u64_t max_attempts) +static void mine_coins_ocl(u64_t max_attempts, double max_time) { ocl_data_t od; u32_t *host_storage; @@ -74,6 +75,17 @@ static void mine_coins_ocl(u64_t max_attempts) printf("Work groups: %zu × %zu = %u total work items\n", od.global_work_size / od.local_work_size, od.local_work_size, n_threads); printf("Kernel: %s\n", od.kernel_name); + + if(max_attempts > 0 && max_time > 0) + printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n", + (unsigned long long)max_attempts, max_time); + else if(max_attempts > 0) + printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts); + else if(max_time > 0) + printf("Will stop after %.2f seconds\n", max_time); + else + printf("Running indefinitely until Ctrl+C...\n"); + printf("Press Ctrl+C to stop\n\n"); u32_t param1 = (u32_t)time(NULL); @@ -81,8 +93,16 @@ static void mine_coins_ocl(u64_t max_attempts) double start_time = get_wall_time(); - while(keep_running && (max_attempts == 0 || attempts < max_attempts)) + while(keep_running) { + // Check stopping conditions + if(max_attempts > 0 && attempts >= max_attempts) + break; + + double elapsed = get_wall_time() - start_time; + if(max_time > 0 && elapsed >= max_time) + break; + // Initialize storage area host_storage[0] = 1u; @@ -135,7 +155,7 @@ static void mine_coins_ocl(u64_t max_attempts) // Print progress every 10 kernel launches if(kernel_runs % 10 == 0) { - double elapsed = get_wall_time() - start_time; + elapsed = get_wall_time() - start_time; double rate = attempts / elapsed; printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Kernels: %u, Elapsed: %.2fs\n", (unsigned long long)attempts, rate / 1e6, coins_found, kernel_runs, elapsed); @@ -157,16 +177,49 @@ static void mine_coins_ocl(u64_t max_attempts) terminate_ocl(&od); } +void print_usage(const char *prog_name) +{ + printf("Usage: %s [OPTIONS]\n", prog_name); + printf("Options:\n"); + printf(" -a Maximum number of attempts\n"); + printf(" -t Maximum time in seconds\n"); + printf(" -h Show this help message\n"); + printf("\nExamples:\n"); + printf(" %s -a 1000000000 # Run for 1B attempts\n", prog_name); + printf(" %s -t 60 # Run for 60 seconds\n", prog_name); + printf(" %s -a 1000000000 -t 60 # Stop at 1B attempts OR 60s (whichever first)\n", prog_name); + printf(" %s # Run indefinitely until Ctrl+C\n", prog_name); +} + int main(int argc, char *argv[]) { u64_t max_attempts = 0; + double max_time = 0; + int opt; signal(SIGINT, signal_handler); - if(argc > 1) - max_attempts = strtoull(argv[1], NULL, 10); + // Parse command line options + while((opt = getopt(argc, argv, "a:t:h")) != -1) + { + switch(opt) + { + case 'a': + max_attempts = strtoull(optarg, NULL, 10); + break; + case 't': + max_time = atof(optarg); + break; + case 'h': + print_usage(argv[0]); + return 0; + default: + print_usage(argv[0]); + return 1; + } + } - mine_coins_ocl(max_attempts); + mine_coins_ocl(max_attempts, max_time); return 0; } diff --git a/aad_coin_miner_simd.c b/aad_coin_miner_simd.c index 42c409a..f96fccc 100644 --- a/aad_coin_miner_simd.c +++ b/aad_coin_miner_simd.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aad_data_types.h" #include "aad_utilities.h" #include "aad_sha1_cpu.h" @@ -129,7 +130,7 @@ static void extract_coins(u32_t *interleaved_data, u32_t coins[][14], int simd_w // mine DETI coins using AVX (4-way SIMD) // __attribute__((unused)) -static void mine_coins_avx(u64_t max_attempts) +static void mine_coins_avx(u64_t max_attempts, double max_time) { const int SIMD_WIDTH = 4; u32_t base_coin[14]; @@ -160,12 +161,31 @@ static void mine_coins_avx(u64_t max_attempts) ((u08_t *)base_coin)[i ^ 3] = 'A' + (i - 12) % 26; printf("Mining DETI coins using AVX (4-way SIMD)...\n"); + + if(max_attempts > 0 && max_time > 0) + printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n", + (unsigned long long)max_attempts, max_time); + else if(max_attempts > 0) + printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts); + else if(max_time > 0) + printf("Will stop after %.2f seconds\n", max_time); + else + printf("Running indefinitely until Ctrl+C...\n"); + printf("Press Ctrl+C to stop\n\n"); double start_time = get_wall_time(); - while(keep_running && (max_attempts == 0 || attempts < max_attempts)) + while(keep_running) { + // Check stopping conditions + if(max_attempts > 0 && attempts >= max_attempts) + break; + + double elapsed = get_wall_time() - start_time; + if(max_time > 0 && elapsed >= max_time) + break; + // Prepare coins for this batch prepare_coins(base_coin, interleaved_data, SIMD_WIDTH); @@ -193,7 +213,7 @@ static void mine_coins_avx(u64_t max_attempts) // Print progress every 1M attempts if(attempts % 1000000 < SIMD_WIDTH) { - double elapsed = get_wall_time() - start_time; + elapsed = get_wall_time() - start_time; double rate = attempts / elapsed; printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n", (unsigned long long)attempts, rate / 1e6, coins_found, elapsed); @@ -217,7 +237,7 @@ static void mine_coins_avx(u64_t max_attempts) // mine DETI coins using AVX2 (8-way SIMD) // __attribute__((unused)) -static void mine_coins_avx2(u64_t max_attempts) +static void mine_coins_avx2(u64_t max_attempts, double max_time) { const int SIMD_WIDTH = 8; u32_t base_coin[14]; @@ -248,12 +268,31 @@ static void mine_coins_avx2(u64_t max_attempts) ((u08_t *)base_coin)[i ^ 3] = 'A' + (i - 12) % 26; printf("Mining DETI coins using AVX2 (8-way SIMD)...\n"); + + if(max_attempts > 0 && max_time > 0) + printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n", + (unsigned long long)max_attempts, max_time); + else if(max_attempts > 0) + printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts); + else if(max_time > 0) + printf("Will stop after %.2f seconds\n", max_time); + else + printf("Running indefinitely until Ctrl+C...\n"); + printf("Press Ctrl+C to stop\n\n"); double start_time = get_wall_time(); - while(keep_running && (max_attempts == 0 || attempts < max_attempts)) + while(keep_running) { + // Check stopping conditions + if(max_attempts > 0 && attempts >= max_attempts) + break; + + double elapsed = get_wall_time() - start_time; + if(max_time > 0 && elapsed >= max_time) + break; + prepare_coins(base_coin, interleaved_data, SIMD_WIDTH); sha1_avx2((v8si *)interleaved_data, (v8si *)interleaved_hash); attempts += SIMD_WIDTH; @@ -276,7 +315,7 @@ static void mine_coins_avx2(u64_t max_attempts) if(attempts % 1000000 < SIMD_WIDTH) { - double elapsed = get_wall_time() - start_time; + elapsed = get_wall_time() - start_time; double rate = attempts / elapsed; printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n", (unsigned long long)attempts, rate / 1e6, coins_found, elapsed); @@ -301,14 +340,26 @@ static void mine_coins_avx2(u64_t max_attempts) // mine DETI coins using AVX2 (8-way SIMD) + OpenMP // __attribute__((unused)) -static void mine_coins_avx2_omp(u64_t max_attempts) +static void mine_coins_avx2_omp(u64_t max_attempts, double max_time) { const int SIMD_WIDTH = 8; int num_threads = omp_get_max_threads(); u64_t attempts = 0; u32_t coins_found = 0; + u64_t last_reported_attempts = 0; printf("Mining DETI coins using AVX2 (8-way SIMD) + OpenMP (%d threads)...\n", num_threads); + + if(max_attempts > 0 && max_time > 0) + printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n", + (unsigned long long)max_attempts, max_time); + else if(max_attempts > 0) + printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts); + else if(max_time > 0) + printf("Will stop after %.2f seconds\n", max_time); + else + printf("Running indefinitely until Ctrl+C...\n"); + printf("Press Ctrl+C to stop\n\n"); double start_time = get_wall_time(); @@ -342,8 +393,16 @@ static void mine_coins_avx2_omp(u64_t max_attempts) for(int i = 12; i < 54; i++) ((u08_t *)base_coin)[i ^ 3] = 'A' + ((i - 12 + thread_id * SIMD_WIDTH) % 26); - while(keep_running && (max_attempts == 0 || (attempts + thread_attempts) < max_attempts)) + while(keep_running) { + // Check stopping conditions + if(max_attempts > 0 && attempts >= max_attempts) + break; + + double elapsed_time = get_wall_time() - start_time; + if(max_time > 0 && elapsed_time >= max_time) + break; + prepare_coins(base_coin, interleaved_data, SIMD_WIDTH); sha1_avx2((v8si *)interleaved_data, (v8si *)interleaved_hash); thread_attempts += SIMD_WIDTH; @@ -368,15 +427,26 @@ static void mine_coins_avx2_omp(u64_t max_attempts) } } - // Print progress every 1M attempts (per thread) - if(thread_attempts % 1000000 < SIMD_WIDTH) + // Print progress every 1M attempts (only from one thread) + // Periodically update the shared counter and report + if(thread_attempts % 100000 < SIMD_WIDTH) { - #pragma omp critical + #pragma omp atomic + attempts += thread_attempts; + thread_attempts = 0; + + #pragma omp barrier + + #pragma omp master { - double elapsed = get_wall_time() - start_time; - double rate = (attempts + thread_attempts) / elapsed; - printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n", - (unsigned long long)(attempts + thread_attempts), rate / 1e6, coins_found, elapsed); + if(attempts - last_reported_attempts >= 1000000) + { + double elapsed = get_wall_time() - start_time; + double rate = attempts / elapsed; + printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n", + (unsigned long long)attempts, rate / 1e6, coins_found, elapsed); + last_reported_attempts = attempts; + } } } } @@ -397,30 +467,123 @@ static void mine_coins_avx2_omp(u64_t max_attempts) } #endif +void print_usage(const char *prog_name) +{ + printf("Usage: %s [OPTIONS]\n", prog_name); + printf("Options:\n"); + printf(" -a Maximum number of attempts\n"); + printf(" -t Maximum time in seconds\n"); + printf(" --avx Use AVX (4-way SIMD)\n"); + printf(" --avx2 Use AVX2 (8-way SIMD)\n"); + printf(" --omp Use AVX2 + OpenMP (multi-threaded)\n"); + printf(" -h Show this help message\n"); + printf("\nNote: Only one SIMD mode (--avx, --avx2, --omp) can be used at a time.\n"); + printf(" If no SIMD mode is specified, the program will auto-detect.\n"); + printf("\nExamples:\n"); + printf(" %s --avx2 -a 1000000 # AVX2 for 1M attempts\n", prog_name); + printf(" %s --omp -t 60 # AVX2+OpenMP for 60 seconds\n", prog_name); + printf(" %s --avx -a 1000000 -t 60 # AVX, stop at 1M or 60s\n", prog_name); +} + int main(int argc, char *argv[]) { u64_t max_attempts = 0; + double max_time = 0; + int use_avx = 0; + int use_avx2 = 0; + int use_omp = 0; + int opt; signal(SIGINT, signal_handler); - if(argc > 1) - max_attempts = strtoull(argv[1], NULL, 10); + // Define long options + static struct option long_options[] = { + {"avx", no_argument, 0, 'x'}, + {"avx2", no_argument, 0, 'y'}, + {"omp", no_argument, 0, 'o'}, + {0, 0, 0, 0} + }; -#if defined(__AVX2__) - if(argc > 2 && strcmp(argv[2], "omp") == 0) { - printf("Using AVX2 + OpenMP implementation\n"); - mine_coins_avx2_omp(max_attempts); - } else { - printf("Using AVX2 implementation\n"); - mine_coins_avx2(max_attempts); + // Parse command line options + int option_index = 0; + while((opt = getopt_long(argc, argv, "a:t:h", long_options, &option_index)) != -1) + { + switch(opt) + { + case 'a': + max_attempts = strtoull(optarg, NULL, 10); + break; + case 't': + max_time = atof(optarg); + break; + case 'x': + use_avx = 1; + break; + case 'y': + use_avx2 = 1; + break; + case 'o': + use_omp = 1; + break; + case 'h': + print_usage(argv[0]); + return 0; + default: + print_usage(argv[0]); + return 1; + } } -#elif defined(__AVX__) - printf("Using AVX implementation\n"); - mine_coins_avx(max_attempts); + + // Check for conflicting SIMD modes + int simd_flags = use_avx + use_avx2 + use_omp; + if(simd_flags > 1) + { + fprintf(stderr, "Error: Only one SIMD mode (--avx, --avx2, --omp) can be specified.\n"); + return 1; + } + + // Execute based on selected mode + if(use_omp) + { +#if defined(__AVX2__) + mine_coins_avx2_omp(max_attempts, max_time); #else - printf("Error: No SIMD instruction set available. Compile with -mavx or -mavx2\n"); - return 1; + fprintf(stderr, "Error: OpenMP mode requires AVX2 support. Compile with -mavx2 -fopenmp\n"); + return 1; #endif + } + else if(use_avx2) + { +#if defined(__AVX2__) + mine_coins_avx2(max_attempts, max_time); +#else + fprintf(stderr, "Error: AVX2 not available. Compile with -mavx2\n"); + return 1; +#endif + } + else if(use_avx) + { +#if defined(__AVX__) + mine_coins_avx(max_attempts, max_time); +#else + fprintf(stderr, "Error: AVX not available. Compile with -mavx\n"); + return 1; +#endif + } + else + { + // Auto-detect: use best available +#if defined(__AVX2__) + printf("Auto-detecting: Using AVX2 implementation\n"); + mine_coins_avx2(max_attempts, max_time); +#elif defined(__AVX__) + printf("Auto-detecting: Using AVX implementation\n"); + mine_coins_avx(max_attempts, max_time); +#else + fprintf(stderr, "Error: No SIMD instruction set available. Compile with -mavx or -mavx2\n"); + return 1; +#endif + } return 0; }