WebAssembly with SIMD
Signed-off-by: Tiago Garcia <tiago.rgarcia@ua.pt>
This commit is contained in:
parent
a906816cd4
commit
4d2bbe4f9b
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Arquiteturas de Alto Desempenho 2025/2026
|
||||
//
|
||||
// DETI Coin Miner - WebAssembly implementation
|
||||
// DETI Coin Miner - WebAssembly implementation with SIMD support
|
||||
//
|
||||
|
||||
#include <time.h>
|
||||
|
|
@ -19,14 +19,20 @@
|
|||
#include "aad_vault.h"
|
||||
#endif
|
||||
|
||||
// WASM SIMD support
|
||||
#if defined(__wasm_simd128__)
|
||||
#include <wasm_simd128.h>
|
||||
#endif
|
||||
|
||||
// Global mining state
|
||||
static volatile int keep_running = 1;
|
||||
static volatile int use_simd = 0;
|
||||
static u64_t total_attempts = 0;
|
||||
static u32_t coins_found = 0;
|
||||
static double mining_start_time = 0;
|
||||
static double pause_time_offset = 0; // Track paused time
|
||||
static double last_pause_time = 0; // When mining was paused
|
||||
static u32_t found_coins[1024][14]; // Store up to 1024 found coins
|
||||
static double pause_time_offset = 0;
|
||||
static double last_pause_time = 0;
|
||||
static u32_t found_coins[1024][14];
|
||||
static u32_t found_coins_count = 0;
|
||||
|
||||
//
|
||||
|
|
@ -82,6 +88,185 @@ static double get_time()
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(__wasm_simd128__)
|
||||
//
|
||||
// Helper macro for Left Rotate (ROTL) using SIMD shifts
|
||||
// CORRECTION: Used wasm_u32x4_shr instead of incorrect wasm_i32x4_shr_u
|
||||
//
|
||||
#define SIMD_ROTL(x, n) wasm_v128_or(wasm_i32x4_shl(x, n), wasm_u32x4_shr(x, 32 - n))
|
||||
|
||||
//
|
||||
// SIMD implementation for WebAssembly (4-way parallel)
|
||||
//
|
||||
static void prepare_coins_simd(u32_t base_coin[14], u32_t *interleaved_data)
|
||||
{
|
||||
const int SIMD_WIDTH = 4;
|
||||
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
||||
{
|
||||
u32_t coin[14];
|
||||
memcpy(coin, base_coin, sizeof(coin));
|
||||
|
||||
for(int idx = 0; idx < 14; idx++)
|
||||
{
|
||||
interleaved_data[idx * SIMD_WIDTH + lane] = coin[idx];
|
||||
}
|
||||
|
||||
increment_coin(base_coin);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_hashes_simd(u32_t *interleaved_hash, u32_t hashes[][5])
|
||||
{
|
||||
const int SIMD_WIDTH = 4;
|
||||
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
||||
{
|
||||
for(int idx = 0; idx < 5; idx++)
|
||||
{
|
||||
hashes[lane][idx] = interleaved_hash[idx * SIMD_WIDTH + lane];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_coins_simd(u32_t *interleaved_data, u32_t coins[][14])
|
||||
{
|
||||
const int SIMD_WIDTH = 4;
|
||||
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
||||
{
|
||||
for(int idx = 0; idx < 14; idx++)
|
||||
{
|
||||
coins[lane][idx] = interleaved_data[idx * SIMD_WIDTH + lane];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sha1_wasm_simd(u32_t *interleaved_data, u32_t *interleaved_hash)
|
||||
{
|
||||
const int SIMD_WIDTH = 4;
|
||||
|
||||
// SHA1 State vectors
|
||||
v128_t a, b, c, d, e;
|
||||
v128_t w[80]; // Message schedule
|
||||
|
||||
// Initial SHA1 constants
|
||||
a = wasm_i32x4_splat(0x67452301u);
|
||||
b = wasm_i32x4_splat(0xEFCDAB89u);
|
||||
c = wasm_i32x4_splat(0x98BADCFEu);
|
||||
d = wasm_i32x4_splat(0x10325476u);
|
||||
e = wasm_i32x4_splat(0xC3D2E1F0u);
|
||||
|
||||
// 1. Prepare Message Schedule (Interleaved loads)
|
||||
// Load first 14 words
|
||||
for(int i = 0; i < 14; i++)
|
||||
{
|
||||
w[i] = wasm_v128_load(&interleaved_data[i * SIMD_WIDTH]);
|
||||
}
|
||||
// Standard padding (assumed handled by caller/init)
|
||||
w[14] = wasm_i32x4_splat(0);
|
||||
w[15] = wasm_i32x4_splat(440); // Length in bits (55 bytes * 8)
|
||||
|
||||
// Expand message schedule from 16 to 80
|
||||
for (int i = 16; i < 80; i++) {
|
||||
v128_t temp = wasm_v128_xor(w[i-3], w[i-8]);
|
||||
temp = wasm_v128_xor(temp, w[i-14]);
|
||||
temp = wasm_v128_xor(temp, w[i-16]);
|
||||
w[i] = SIMD_ROTL(temp, 1);
|
||||
}
|
||||
|
||||
// 2. Main Loop (80 rounds)
|
||||
for (int i = 0; i < 80; i++) {
|
||||
v128_t f, k;
|
||||
|
||||
if (i < 20) {
|
||||
// F1: (b & c) | (~b & d)
|
||||
f = wasm_v128_or(wasm_v128_and(b, c), wasm_v128_and(wasm_v128_not(b), d));
|
||||
k = wasm_i32x4_splat(0x5A827999u);
|
||||
} else if (i < 40) {
|
||||
// F2: b ^ c ^ d
|
||||
f = wasm_v128_xor(wasm_v128_xor(b, c), d);
|
||||
k = wasm_i32x4_splat(0x6ED9EBA1u);
|
||||
} else if (i < 60) {
|
||||
// F3: (b & c) | (b & d) | (c & d)
|
||||
f = wasm_v128_or(wasm_v128_or(wasm_v128_and(b, c), wasm_v128_and(b, d)), wasm_v128_and(c, d));
|
||||
k = wasm_i32x4_splat(0x8F1BBCDCu);
|
||||
} else {
|
||||
// F4: b ^ c ^ d
|
||||
f = wasm_v128_xor(wasm_v128_xor(b, c), d);
|
||||
k = wasm_i32x4_splat(0xCA62C1D6u);
|
||||
}
|
||||
|
||||
// temp = ROTL(a, 5) + f + e + k + w[i]
|
||||
v128_t temp = wasm_i32x4_add(SIMD_ROTL(a, 5), f);
|
||||
temp = wasm_i32x4_add(temp, e);
|
||||
temp = wasm_i32x4_add(temp, k);
|
||||
temp = wasm_i32x4_add(temp, w[i]);
|
||||
|
||||
e = d;
|
||||
d = c;
|
||||
c = SIMD_ROTL(b, 30);
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
// 3. Add to initial state and store
|
||||
v128_t h0 = wasm_i32x4_add(a, wasm_i32x4_splat(0x67452301u));
|
||||
v128_t h1 = wasm_i32x4_add(b, wasm_i32x4_splat(0xEFCDAB89u));
|
||||
v128_t h2 = wasm_i32x4_add(c, wasm_i32x4_splat(0x98BADCFEu));
|
||||
v128_t h3 = wasm_i32x4_add(d, wasm_i32x4_splat(0x10325476u));
|
||||
v128_t h4 = wasm_i32x4_add(e, wasm_i32x4_splat(0xC3D2E1F0u));
|
||||
|
||||
// Store results back to interleaved_hash
|
||||
wasm_v128_store(&interleaved_hash[0 * SIMD_WIDTH], h0);
|
||||
wasm_v128_store(&interleaved_hash[1 * SIMD_WIDTH], h1);
|
||||
wasm_v128_store(&interleaved_hash[2 * SIMD_WIDTH], h2);
|
||||
wasm_v128_store(&interleaved_hash[3 * SIMD_WIDTH], h3);
|
||||
wasm_v128_store(&interleaved_hash[4 * SIMD_WIDTH], h4);
|
||||
}
|
||||
|
||||
static int mine_coins_wasm_simd_internal(u32_t iterations_per_call, u32_t coin[14])
|
||||
{
|
||||
const int SIMD_WIDTH = 4;
|
||||
u32_t interleaved_data[14 * SIMD_WIDTH] __attribute__((aligned(16)));
|
||||
u32_t interleaved_hash[5 * SIMD_WIDTH] __attribute__((aligned(16)));
|
||||
|
||||
u32_t batches = (iterations_per_call + SIMD_WIDTH - 1) / SIMD_WIDTH;
|
||||
|
||||
for(u32_t batch = 0; batch < batches && keep_running; batch++)
|
||||
{
|
||||
prepare_coins_simd(coin, interleaved_data);
|
||||
|
||||
// This now uses the REAL vectorized implementation
|
||||
sha1_wasm_simd(interleaved_data, interleaved_hash);
|
||||
|
||||
total_attempts += SIMD_WIDTH;
|
||||
|
||||
u32_t hashes[SIMD_WIDTH][5];
|
||||
extract_hashes_simd(interleaved_hash, hashes);
|
||||
|
||||
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
||||
{
|
||||
if(is_valid_coin(hashes[lane]))
|
||||
{
|
||||
if(found_coins_count < 1024)
|
||||
{
|
||||
u32_t coins[SIMD_WIDTH][14];
|
||||
extract_coins_simd(interleaved_data, coins);
|
||||
memcpy(found_coins[found_coins_count], coins[lane], sizeof(coins[lane]));
|
||||
found_coins_count++;
|
||||
}
|
||||
coins_found++;
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
printf("COIN FOUND! (attempt %llu, lane %d)\n",
|
||||
(unsigned long long)(total_attempts - SIMD_WIDTH + lane), lane);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keep_running;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Main mining iteration (called from JavaScript)
|
||||
//
|
||||
|
|
@ -92,6 +277,8 @@ int mine_coins_wasm(u32_t iterations_per_call)
|
|||
{
|
||||
static u32_t coin[14];
|
||||
static int initialized = 0;
|
||||
static int last_logged_mode = -1; // Track last reported mode
|
||||
|
||||
u32_t hash[5];
|
||||
|
||||
// Initialize coin template on first call
|
||||
|
|
@ -123,7 +310,23 @@ int mine_coins_wasm(u32_t iterations_per_call)
|
|||
if(!keep_running)
|
||||
return 0;
|
||||
|
||||
// Mine for the specified number of iterations
|
||||
#if defined(__wasm_simd128__)
|
||||
if(use_simd)
|
||||
{
|
||||
if (last_logged_mode != 1) {
|
||||
printf("C: Running in SIMD Mode (Vectorized)\n");
|
||||
last_logged_mode = 1;
|
||||
}
|
||||
return mine_coins_wasm_simd_internal(iterations_per_call, coin);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (last_logged_mode != 0) {
|
||||
printf("C: Running in Scalar Mode\n");
|
||||
last_logged_mode = 0;
|
||||
}
|
||||
|
||||
// Scalar implementation
|
||||
for(u32_t i = 0; i < iterations_per_call && keep_running; i++)
|
||||
{
|
||||
sha1(coin, hash);
|
||||
|
|
@ -165,10 +368,8 @@ void get_statistics(u64_t *attempts, u32_t *coins, double *hash_rate, double *el
|
|||
double actual_elapsed;
|
||||
|
||||
if(!keep_running && last_pause_time > 0) {
|
||||
// If paused, use the paused time
|
||||
actual_elapsed = last_pause_time - mining_start_time - pause_time_offset;
|
||||
} else {
|
||||
// If running, calculate normally
|
||||
actual_elapsed = current_time - mining_start_time - pause_time_offset;
|
||||
}
|
||||
|
||||
|
|
@ -176,6 +377,44 @@ void get_statistics(u64_t *attempts, u32_t *coins, double *hash_rate, double *el
|
|||
*hash_rate = (actual_elapsed > 0) ? (total_attempts / actual_elapsed) : 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Enable/disable SIMD
|
||||
//
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
#endif
|
||||
void set_simd_enabled(int enabled)
|
||||
{
|
||||
use_simd = enabled;
|
||||
printf("C: SIMD mode set to: %d\n", use_simd);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if SIMD is available
|
||||
//
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
#endif
|
||||
int is_simd_available()
|
||||
{
|
||||
#if defined(__wasm_simd128__)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Get current SIMD state
|
||||
//
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
#endif
|
||||
int is_simd_enabled()
|
||||
{
|
||||
return use_simd;
|
||||
}
|
||||
|
||||
//
|
||||
// Stop mining
|
||||
//
|
||||
|
|
@ -207,7 +446,7 @@ void resume_mining()
|
|||
}
|
||||
|
||||
//
|
||||
// Get found coin data (returns pointer to coin array)
|
||||
// Get found coin data
|
||||
//
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
|
|
@ -259,6 +498,12 @@ int main(int argc, char *argv[])
|
|||
max_attempts = strtoull(argv[1], NULL, 10);
|
||||
|
||||
printf("Mining DETI coins using WebAssembly implementation (standalone mode)...\n");
|
||||
#if defined(__wasm_simd128__)
|
||||
printf("SIMD support: available\n");
|
||||
use_simd = 1;
|
||||
#else
|
||||
printf("SIMD support: not available\n");
|
||||
#endif
|
||||
printf("Press Ctrl+C to stop\n\n");
|
||||
|
||||
time_measurement();
|
||||
|
|
|
|||
157
index.html
157
index.html
|
|
@ -13,6 +13,11 @@
|
|||
padding: 10px 20px;
|
||||
margin: 5px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
#stats {
|
||||
margin-top: 20px;
|
||||
|
|
@ -56,22 +61,96 @@
|
|||
.coin-data {
|
||||
color: #000080;
|
||||
}
|
||||
.simd-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.toggle-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
}
|
||||
.toggle-switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
transition: .4s;
|
||||
border-radius: 34px;
|
||||
}
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
transition: .4s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(26px);
|
||||
}
|
||||
input:disabled + .slider {
|
||||
background-color: #ddd;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.simd-status {
|
||||
font-weight: bold;
|
||||
}
|
||||
.simd-available {
|
||||
color: #28a745;
|
||||
}
|
||||
.simd-unavailable {
|
||||
color: #dc3545;
|
||||
}
|
||||
.button-group {
|
||||
margin: 15px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>DETI Coin Miner (WebAssembly)</h1>
|
||||
|
||||
<div class="control-group simd-toggle">
|
||||
<label>Enable SIMD:</label>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="simdToggle">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span id="simdStatus" class="simd-status"></span>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label>Iterations per batch:</label>
|
||||
<input type="number" id="batchSize" value="1000000" step="100000">
|
||||
<input type="number" id="batchSize" value="1000000" step="100000" min="100000">
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label>Update interval (ms):</label>
|
||||
<input type="number" id="updateInterval" value="100" step="50">
|
||||
<input type="number" id="updateInterval" value="100" step="50" min="50">
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button id="start">Start Mining</button>
|
||||
<button id="stop">Stop Mining</button>
|
||||
<button id="reset">Reset</button>
|
||||
<button id="clearCoins">Clear Coins Display</button>
|
||||
</div>
|
||||
<button id="start">Start Mining</button>
|
||||
<button id="stop">Stop Mining</button>
|
||||
<button id="reset">Reset</button>
|
||||
<button id="clearCoins">Clear Coins Display</button>
|
||||
|
||||
<div id="stats">
|
||||
Waiting to start...
|
||||
|
|
@ -90,11 +169,56 @@
|
|||
let updateInterval;
|
||||
let lastDisplayedCoinCount = 0;
|
||||
let pausedStats = false;
|
||||
let simdAvailable = false;
|
||||
|
||||
CoinMinerModule().then(mod => {
|
||||
Module = mod;
|
||||
console.log('WebAssembly module loaded');
|
||||
|
||||
// Check if SIMD is available
|
||||
simdAvailable = Module._is_simd_available();
|
||||
const simdToggle = document.getElementById('simdToggle');
|
||||
const simdStatus = document.getElementById('simdStatus');
|
||||
|
||||
if (simdAvailable) {
|
||||
simdStatus.textContent = 'SIMD Available';
|
||||
simdStatus.className = 'simd-status simd-available';
|
||||
simdToggle.disabled = false;
|
||||
|
||||
// SYNC LOGIC: Read C state first to match backend
|
||||
const cState = Module._is_simd_enabled();
|
||||
simdToggle.checked = (cState === 1);
|
||||
|
||||
// Force sync again just to be safe
|
||||
Module._set_simd_enabled(simdToggle.checked ? 1 : 0);
|
||||
console.log(`JS: Initialized - SIMD Available, Toggle set to ${simdToggle.checked}`);
|
||||
} else {
|
||||
simdStatus.textContent = 'SIMD Not Available';
|
||||
simdStatus.className = 'simd-status simd-unavailable';
|
||||
simdToggle.disabled = true;
|
||||
simdToggle.checked = false;
|
||||
Module._set_simd_enabled(0);
|
||||
console.log('JS: Initialized - SIMD Not Available');
|
||||
}
|
||||
|
||||
// SIMD toggle handler
|
||||
simdToggle.onchange = () => {
|
||||
if (simdAvailable) {
|
||||
const newState = simdToggle.checked ? 1 : 0;
|
||||
console.log(`JS: User toggled SIMD to ${newState}`);
|
||||
|
||||
// Call the C function
|
||||
Module._set_simd_enabled(newState);
|
||||
|
||||
// Update status display
|
||||
const currentMode = simdToggle.checked ? 'SIMD Mode' : 'Scalar Mode';
|
||||
if (!mining) {
|
||||
document.getElementById('stats').innerHTML =
|
||||
`${currentMode} selected. Click Start to begin mining.`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById('start').onclick = () => {
|
||||
if (!mining) {
|
||||
mining = true;
|
||||
|
|
@ -114,10 +238,10 @@
|
|||
updateStats();
|
||||
|
||||
let currentHTML = document.getElementById('stats').innerHTML;
|
||||
document.getElementById('stats').innerHTML = currentHTML.replace('Mining Statistics:', 'Mining Statistics (PAUSED):');
|
||||
document.getElementById('stats').innerHTML =
|
||||
currentHTML.replace('Mining Statistics:', 'Mining Statistics (PAUSED):');
|
||||
|
||||
pausedStats = true;
|
||||
|
||||
console.log('Mining stopped');
|
||||
};
|
||||
|
||||
|
|
@ -128,7 +252,10 @@
|
|||
clearInterval(miningInterval);
|
||||
clearInterval(updateInterval);
|
||||
lastDisplayedCoinCount = 0;
|
||||
document.getElementById('stats').innerHTML = 'Reset complete. Click Start to begin.';
|
||||
|
||||
const mode = simdToggle.checked ? 'SIMD' : 'Scalar';
|
||||
document.getElementById('stats').innerHTML =
|
||||
`Reset complete. Using ${mode} mode. Click Start to begin.`;
|
||||
document.getElementById('coins').innerHTML = '';
|
||||
document.getElementById('coin-count').textContent = '0';
|
||||
console.log('Mining reset');
|
||||
|
|
@ -175,7 +302,8 @@
|
|||
const timestamp = new Date().toLocaleTimeString();
|
||||
|
||||
const entry = document.createElement('div');
|
||||
entry.innerHTML = `<span class="coin-entry">[${timestamp}] Coin #${i + 1}:</span> <span class="coin-data">${coinStr}</span>`;
|
||||
entry.innerHTML =
|
||||
`<span class="coin-entry">[${timestamp}] Coin #${i + 1}:</span> <span class="coin-data">${coinStr}</span>`;
|
||||
coinsDiv.appendChild(entry);
|
||||
|
||||
coinsDiv.scrollTop = coinsDiv.scrollHeight;
|
||||
|
|
@ -193,23 +321,18 @@
|
|||
const hashRatePtr = Module._malloc(8);
|
||||
const elapsedPtr = Module._malloc(8);
|
||||
|
||||
// Zero-initialize the memory before calling
|
||||
Module.setValue(attemptsPtr, 0, 'i32');
|
||||
Module.setValue(attemptsPtr + 4, 0, 'i32');
|
||||
|
||||
Module._get_statistics(attemptsPtr, coinsPtr, hashRatePtr, elapsedPtr);
|
||||
|
||||
// Read 64-bit unsigned value correctly
|
||||
// On little-endian, low 32 bits come first
|
||||
const attemptsLowUnsigned = Module.getValue(attemptsPtr, 'i32') >>> 0;
|
||||
const attemptsHighUnsigned = Module.getValue(attemptsPtr + 4, 'i32') >>> 0;
|
||||
|
||||
// Combine - for display purposes, if high part is 0, just show low part
|
||||
let attempts;
|
||||
if (attemptsHighUnsigned === 0) {
|
||||
attempts = attemptsLowUnsigned;
|
||||
} else {
|
||||
// Use BigInt for values > 32 bits
|
||||
const low = BigInt(attemptsLowUnsigned);
|
||||
const high = BigInt(attemptsHighUnsigned);
|
||||
attempts = (high * BigInt(4294967296)) + low;
|
||||
|
|
@ -224,8 +347,10 @@
|
|||
Module._free(hashRatePtr);
|
||||
Module._free(elapsedPtr);
|
||||
|
||||
const mode = Module._is_simd_enabled() ? 'SIMD' : 'Scalar';
|
||||
|
||||
document.getElementById('stats').innerHTML = `
|
||||
<strong>Mining Statistics:</strong><br>
|
||||
<strong>Mining Statistics (${mode} Mode):</strong><br>
|
||||
Attempts: ${attempts.toString()}<br>
|
||||
Coins Found: ${coins}<br>
|
||||
Hash Rate: ${(hashRate / 1e6).toFixed(2)} MH/s<br>
|
||||
|
|
|
|||
2
makefile
2
makefile
|
|
@ -86,7 +86,7 @@ coin_miner_cuda: aad_coin_miner_cuda.c coin_miner_cuda_kernel.cubin aad_sha1.h a
|
|||
cc -march=native -Wall -Wshadow -Werror -O3 -I$(CUDA_DIR)/include $< -o $@ -lcuda
|
||||
|
||||
coin_miner_wasm: aad_coin_miner_wasm.c aad_sha1.h aad_sha1_cpu.h aad_sha1_wasm.h aad_data_types.h aad_utilities.h aad_vault.h makefile
|
||||
emcc -O3 -flto -o coin_miner_wasm.js aad_coin_miner_wasm.c \
|
||||
emcc -O3 -flto -msimd128 -o coin_miner_wasm.js aad_coin_miner_wasm.c \
|
||||
-s WASM=1 \
|
||||
-s EXPORTED_FUNCTIONS='["_mine_coins_wasm","_get_statistics","_stop_mining","_reset_mining","_get_found_coin","_get_found_coins_count","_malloc","_free"]' \
|
||||
-s EXPORTED_RUNTIME_METHODS='["cwrap","ccall","getValue","setValue"]' \
|
||||
|
|
|
|||
Loading…
Reference in New Issue