aad-assignment-1/aad_coin_miner_cuda.c

213 lines
5.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Arquiteturas de Alto Desempenho 2025/2026
//
// DETI Coin Miner - CUDA implementation with histograms
//
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <getopt.h>
#include "aad_data_types.h"
#include "aad_utilities.h"
#include "aad_sha1_cpu.h"
#include "aad_cuda_utilities.h"
#include "aad_vault.h"
#define COINS_STORAGE_SIZE 1024u
#define MAX_HISTOGRAM_BINS 100
static volatile int keep_running = 1;
void signal_handler(int signum)
{
(void)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])
{
// Simply copy the complete coin data from storage
for(int i = 0; i < 14; i++)
coin[i] = stored_data[i];
}
//
// Mine DETI coins using CUDA
//
static void mine_coins_cuda(u64_t max_attempts, double max_time)
{
cuda_data_t cd;
u32_t *host_storage;
u64_t attempts = 0;
u32_t coins_found = 0;
u32_t kernel_runs = 0;
// Initialize CUDA
cd.device_number = 0;
cd.cubin_file_name = "coin_miner_cuda_kernel.cubin";
cd.kernel_name = "mine_deti_coins_kernel";
cd.data_size[0] = COINS_STORAGE_SIZE * sizeof(u32_t);
cd.data_size[1] = 0;
initialize_cuda(&cd);
host_storage = (u32_t *)cd.host_data[0];
// Kernel configuration
cd.block_dim_x = RECOMMENDED_CUDA_BLOCK_SIZE;
cd.grid_dim_x = 4096; // Large grid for maximum GPU utilization
u32_t n_threads = cd.grid_dim_x * cd.block_dim_x;
printf("Mining DETI coins using CUDA...\n");
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)
{
// 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
// Copy to device
host_to_device_copy(&cd, 0);
// Set kernel arguments
cd.n_kernel_arguments = 2;
cd.arg[0] = &cd.device_data[0];
cd.arg[1] = &base_nonce;
cd.arg[2] = &attempts_per_thread;
// Launch the CUDA kernel
launch_kernel(&cd);
// Copy results back
device_to_host_copy(&cd, 0);
// Process found coins
u32_t n_coins_this_kernel = 0;
u32_t n_stored = (host_storage[0] - 1) / 14;
if(n_stored > 0 && host_storage[0] < COINS_STORAGE_SIZE)
{
for(u32_t i = 0; i < n_stored; i++)
{
u32_t coin[14];
reconstruct_coin(&host_storage[1 + i * 14], coin);
coins_found++;
n_coins_this_kernel++;
printf("COIN FOUND! (kernel %u, coin %u in this kernel). Total coins:%u\n",
kernel_runs, n_coins_this_kernel, coins_found);
save_coin(coin);
}
}
// Update counters
kernel_runs++;
u64_t attempts_this_launch = (u64_t)n_threads * attempts_per_thread;
attempts += attempts_this_launch;
base_nonce += attempts_this_launch;
}
time_measurement();
double total_time = cpu_time_delta();
printf("\n=== Mining Statistics ===\n");
printf("Total attempts: %llu\n", (unsigned long long)attempts);
printf("Total time: %.2f seconds\n", total_time);
printf("Average rate: %.2f attempts/second\n", attempts / total_time);
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 <attempts> Maximum number of attempts\n");
printf(" -t <seconds> 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);
// 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, max_time);
return 0;
}