213 lines
5.5 KiB
C
213 lines
5.5 KiB
C
//
|
||
// 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;
|
||
}
|