aad-assignment-1/aad_coin_miner_ocl.c

188 lines
4.7 KiB
C
Raw 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 - OpenCL implementation
//
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "aad_data_types.h"
#include "aad_utilities.h"
#include "aad_sha1_cpu.h"
#include "aad_ocl_utilities.h"
#include "aad_vault.h"
#define COINS_STORAGE_SIZE 1024u
static volatile int keep_running = 1;
void signal_handler(int signum)
{
(void)signum;
keep_running = 0;
}
// Coin reconstruction from stored data
static void reconstruct_coin(u32_t *stored_data, u32_t coin[14])
{
for(int i = 0; i < 14; i++)
coin[i] = stored_data[i];
}
// 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;
}
//
// Mine DETI coins using OpenCL
//
static void mine_coins_ocl(u64_t max_attempts, int use_scan_kernel)
{
ocl_data_t od;
u32_t *host_storage;
u64_t attempts = 0;
u32_t coins_found = 0;
u32_t kernel_runs = 0;
// Initialize OpenCL
od.platform_number = 0;
od.device_number = 0;
od.kernel_file_name = "aad_coin_miner_ocl_kernel.cl";
od.kernel_name = use_scan_kernel ? "mine_deti_coins_scan_kernel" : "mine_deti_coins_kernel";
od.data_size[0] = COINS_STORAGE_SIZE * sizeof(u32_t);
od.data_size[1] = 0;
initialize_ocl(&od);
host_storage = (u32_t *)od.host_data[0];
// Kernel configuration
od.local_work_size = RECOMMENDED_OCL_WORK_GROUP_SIZE;
od.global_work_size = 4096 * od.local_work_size;
u32_t n_threads = od.global_work_size;
printf("Mining DETI coins using OpenCL...\n");
printf("Device: %s\n", od.device_name);
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);
printf("Press Ctrl+C to stop\n\n");
u32_t param1 = (u32_t)time(NULL);
u32_t param2 = 0x12345678u;
int scan_pos = 12;
double start_time = get_wall_time();
while(keep_running && (max_attempts == 0 || attempts < max_attempts))
{
// Initialize storage area
host_storage[0] = 1u;
// Copy to device
host_to_device_copy(&od, 0);
// Set kernel arguments
od.n_kernel_arguments = use_scan_kernel ? 4 : 3;
set_kernel_arg(&od, 0, sizeof(cl_mem), &od.device_data[0]);
set_kernel_arg(&od, 1, sizeof(u32_t), &param1);
set_kernel_arg(&od, 2, sizeof(u32_t), &param2);
if(use_scan_kernel)
set_kernel_arg(&od, 3, sizeof(int), &scan_pos);
// Launch the OpenCL kernel
launch_kernel(&od);
// Copy results back
device_to_host_copy(&od, 0);
// Process found coins
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);
// Verify it's actually a valid coin
u32_t hash[5];
sha1(coin, hash);
if(hash[0] == 0xAAD20250u)
{
coins_found++;
printf("COIN FOUND! (kernel %u)\n", kernel_runs);
save_coin(coin);
}
}
}
// Update counters
kernel_runs++;
if(use_scan_kernel)
attempts += n_threads * 95; // Each thread tries 95 printable ASCII values
else
attempts += n_threads;
// Update parameters for next iteration
param1++;
param2 = param2 ^ 0x9E3779B9u;
if(use_scan_kernel)
scan_pos = (scan_pos + 1) % 42 + 12;
// Print progress every 10 kernel launches
if(kernel_runs % 10 == 0)
{
double 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);
}
}
double total_time = get_wall_time() - start_time;
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_ocl(&od);
}
int main(int argc, char *argv[])
{
u64_t max_attempts = 0;
int use_scan_kernel = 0;
signal(SIGINT, signal_handler);
if(argc > 1)
max_attempts = strtoull(argv[1], NULL, 10);
if(argc > 2 && strcmp(argv[2], "scan") == 0)
{
use_scan_kernel = 1;
printf("Using scan kernel (tries 95 values per thread)\n");
}
mine_coins_ocl(max_attempts, use_scan_kernel);
return 0;
}