Skip to content

Commit

Permalink
Doesn't start the miner if no workers available + added fallback for …
Browse files Browse the repository at this point in the history
…amd binaries
  • Loading branch information
tmrlvi committed Apr 8, 2022
1 parent 8bf16e6 commit bfdca32
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 171 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ jobs:
uses: Jimver/cuda-toolkit@v0.2.5
with:
cuda: '11.5.1'
method: 'network'
sub-packages: '["nvcc", "cudart"]'
#method: 'local'
#sub-packages: '["nvcc", "cudart"]'

- name: Build on Linux GNU
if: matrix.os == 'ubuntu-18.04'
Expand Down
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

129 changes: 65 additions & 64 deletions plugins/cuda/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,81 +49,82 @@ impl Plugin for CudaPlugin {
}

//noinspection RsTypeCheck
fn process_option(&mut self, matches: &ArgMatches) -> Result<(), kaspa_miner::Error> {
fn process_option(&mut self, matches: &ArgMatches) -> Result<usize, kaspa_miner::Error> {
let opts: CudaOpt = CudaOpt::from_arg_matches(matches)?;

self._enabled = !opts.cuda_disable;
if self._enabled {
let gpus: Vec<u16> = match &opts.cuda_device {
Some(devices) => devices.clone(),
None => {
let gpu_count = Device::num_devices().unwrap() as u16;
(0..gpu_count).collect()
}
};

// if any of cuda_lock_core_clocks / cuda_lock_mem_clocks / cuda_power_limit is valid, init nvml and try to apply
if opts.cuda_lock_core_clocks.is_some()
|| opts.cuda_lock_mem_clocks.is_some()
|| opts.cuda_power_limits.is_some()
{
for i in 0..gpus.len() {
let lock_mem_clock: Option<u32> = match &opts.cuda_lock_mem_clocks {
Some(mem_clocks) if i < mem_clocks.len() => Some(mem_clocks[i]),
Some(mem_clocks) if !mem_clocks.is_empty() => Some(*mem_clocks.last().unwrap()),
_ => None,
};

let gpus: Vec<u16> = match &opts.cuda_device {
Some(devices) => devices.clone(),
None => {
let gpu_count = Device::num_devices().unwrap() as u16;
(0..gpu_count).collect()
}
};

// if any of cuda_lock_core_clocks / cuda_lock_mem_clocks / cuda_power_limit is valid, init nvml and try to apply
if opts.cuda_lock_core_clocks.is_some()
|| opts.cuda_lock_mem_clocks.is_some()
|| opts.cuda_power_limits.is_some()
{
for i in 0..gpus.len() {
let lock_mem_clock: Option<u32> = match &opts.cuda_lock_mem_clocks {
Some(mem_clocks) if i < mem_clocks.len() => Some(mem_clocks[i]),
Some(mem_clocks) if !mem_clocks.is_empty() => Some(*mem_clocks.last().unwrap()),
_ => None,
};

let lock_core_clock: Option<u32> = match &opts.cuda_lock_core_clocks {
Some(core_clocks) if i < core_clocks.len() => Some(core_clocks[i]),
Some(core_clocks) if !core_clocks.is_empty() => Some(*core_clocks.last().unwrap()),
_ => None,
};

let power_limit: Option<u32> = match &opts.cuda_power_limits {
Some(power_limits) if i < power_limits.len() => Some(power_limits[i]),
Some(power_limits) if !power_limits.is_empty() => Some(*power_limits.last().unwrap()),
_ => None,
};

let mut nvml_device: NvmlDevice = self.nvml_instance.device_by_index(gpus[i] as u32)?;

if let Some(lmc) = lock_mem_clock {
match nvml_device.set_mem_locked_clocks(lmc, lmc) {
Err(e) => error!("set mem locked clocks {:?}", e),
_ => info!("GPU #{} #{} lock mem clock at {} Mhz", i, &nvml_device.name()?, &lmc),
let lock_core_clock: Option<u32> = match &opts.cuda_lock_core_clocks {
Some(core_clocks) if i < core_clocks.len() => Some(core_clocks[i]),
Some(core_clocks) if !core_clocks.is_empty() => Some(*core_clocks.last().unwrap()),
_ => None,
};
}

if let Some(lcc) = lock_core_clock {
match nvml_device.set_gpu_locked_clocks(lcc, lcc) {
Err(e) => error!("set gpu locked clocks {:?}", e),
_ => info!("GPU #{} #{} lock core clock at {} Mhz", i, &nvml_device.name()?, &lcc),
let power_limit: Option<u32> = match &opts.cuda_power_limits {
Some(power_limits) if i < power_limits.len() => Some(power_limits[i]),
Some(power_limits) if !power_limits.is_empty() => Some(*power_limits.last().unwrap()),
_ => None,
};
};

if let Some(pl) = power_limit {
match nvml_device.set_power_management_limit(pl * 1000) {
Err(e) => error!("set power limit {:?}", e),
_ => info!("GPU #{} #{} power limit at {} W", i, &nvml_device.name()?, &pl),
let mut nvml_device: NvmlDevice = self.nvml_instance.device_by_index(gpus[i] as u32)?;

if let Some(lmc) = lock_mem_clock {
match nvml_device.set_mem_locked_clocks(lmc, lmc) {
Err(e) => error!("set mem locked clocks {:?}", e),
_ => info!("GPU #{} #{} lock mem clock at {} Mhz", i, &nvml_device.name()?, &lmc),
};
}

if let Some(lcc) = lock_core_clock {
match nvml_device.set_gpu_locked_clocks(lcc, lcc) {
Err(e) => error!("set gpu locked clocks {:?}", e),
_ => info!("GPU #{} #{} lock core clock at {} Mhz", i, &nvml_device.name()?, &lcc),
};
};
};

if let Some(pl) = power_limit {
match nvml_device.set_power_management_limit(pl * 1000) {
Err(e) => error!("set power limit {:?}", e),
_ => info!("GPU #{} #{} power limit at {} W", i, &nvml_device.name()?, &pl),
};
};
}
}
}

self.specs = (0..gpus.len())
.map(|i| CudaWorkerSpec {
device_id: gpus[i] as u32,
workload: match &opts.cuda_workload {
Some(workload) if i < workload.len() => workload[i],
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
_ => DEFAULT_WORKLOAD_SCALE,
},
is_absolute: opts.cuda_workload_absolute,
blocking_sync: !opts.cuda_no_blocking_sync,
})
.collect();
Ok(())
self.specs = (0..gpus.len())
.map(|i| CudaWorkerSpec {
device_id: gpus[i] as u32,
workload: match &opts.cuda_workload {
Some(workload) if i < workload.len() => workload[i],
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
_ => DEFAULT_WORKLOAD_SCALE,
},
is_absolute: opts.cuda_workload_absolute,
blocking_sync: !opts.cuda_no_blocking_sync,
})
.collect();
}
Ok(self.specs.len())
}
}

Expand Down
1 change: 1 addition & 0 deletions plugins/opencl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ env_logger = "0.9"
opencl3 = {version = "0.6", features = ["CL_VERSION_2_1", "CL_VERSION_2_2", "CL_VERSION_3_0"]}
log = "0.4"
rand = "0.8"
include_dir = "0.7"

[lib]
crate-type = ["cdylib"]
Expand Down
67 changes: 34 additions & 33 deletions plugins/opencl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl Plugin for OpenCLPlugin {
}

//noinspection RsTypeCheck
fn process_option(&mut self, matches: &ArgMatches) -> Result<(), kaspa_miner::Error> {
fn process_option(&mut self, matches: &ArgMatches) -> Result<usize, kaspa_miner::Error> {
let opts: OpenCLOpt = OpenCLOpt::from_arg_matches(matches)?;

self._enabled = opts.opencl_enable;
Expand Down Expand Up @@ -77,38 +77,39 @@ impl Plugin for OpenCLPlugin {
}
None => &platforms[0],
};
info!(
"Chose to mine on {}: {}.",
&_platform.vendor().unwrap_or_else(|_| "Unk".into()),
&_platform.name().unwrap_or_else(|_| "Unk".into())
);

let device_ids = _platform.get_devices(CL_DEVICE_TYPE_ALL).unwrap();
let gpus = match opts.opencl_device {
Some(dev) => {
self._enabled = true;
dev.iter().map(|d| device_ids[*d as usize]).collect::<Vec<cl_device_id>>()
}
None => device_ids,
};

self.specs = (0..gpus.len())
.map(|i| OpenCLWorkerSpec {
_platform: *_platform,
device_id: Device::new(gpus[i]),
workload: match &opts.opencl_workload {
Some(workload) if i < workload.len() => workload[i],
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
_ => DEFAULT_WORKLOAD_SCALE,
},
is_absolute: opts.opencl_workload_absolute,
experimental_amd: opts.experimental_amd,
use_amd_binary: !opts.opencl_no_amd_binary,
random: opts.nonce_gen,
})
.collect();

Ok(())
if self._enabled {
info!(
"Chose to mine on {}: {}.",
&_platform.vendor().unwrap_or_else(|_| "Unk".into()),
&_platform.name().unwrap_or_else(|_| "Unk".into())
);

let device_ids = _platform.get_devices(CL_DEVICE_TYPE_ALL).unwrap();
let gpus = match opts.opencl_device {
Some(dev) => {
self._enabled = true;
dev.iter().map(|d| device_ids[*d as usize]).collect::<Vec<cl_device_id>>()
}
None => device_ids,
};

self.specs = (0..gpus.len())
.map(|i| OpenCLWorkerSpec {
_platform: *_platform,
device_id: Device::new(gpus[i]),
workload: match &opts.opencl_workload {
Some(workload) if i < workload.len() => workload[i],
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
_ => DEFAULT_WORKLOAD_SCALE,
},
is_absolute: opts.opencl_workload_absolute,
experimental_amd: opts.experimental_amd,
use_amd_binary: !opts.opencl_no_amd_binary,
random: opts.nonce_gen,
})
.collect();
}
Ok(self.specs.len())
}
}

Expand Down
81 changes: 17 additions & 64 deletions plugins/opencl/src/worker.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::cli::NonceGenEnum;
use crate::Error;
use include_dir::{include_dir, Dir};
use kaspa_miner::xoshiro256starstar::Xoshiro256StarStar;
use kaspa_miner::Worker;
use log::info;
use log::{info, warn};
use opencl3::command_queue::{CommandQueue, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE};
use opencl3::context::Context;
use opencl3::device::Device;
Expand All @@ -18,6 +19,7 @@ use std::ffi::c_void;
use std::ptr;
use std::sync::Arc;

static BINARY_DIR: Dir = include_dir!("./plugins/opencl/resources/bin/");
static PROGRAM_SOURCE: &str = include_str!("../resources/kaspa-opencl.cl");

pub struct OpenCLGPUWorker {
Expand Down Expand Up @@ -197,70 +199,21 @@ impl OpenCLGPUWorker {

let program = match use_binary {
true => {
let device_name = device.name().unwrap_or_else(|_| "Unknown".into()).to_lowercase();
let mut device_name = device.name().unwrap_or_else(|_| "Unknown".into()).to_lowercase();
if device_name.contains(':') {
device_name = device_name.split_once(':').expect("We checked for `:`").0.to_string();
}
info!("{}: Looking for binary for {}", name, device_name);
match device_name.as_str() {
/*"ellesmere" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/ellesmere_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|e| {
panic!("{}::Program::create_and_build_from_binary failed: {}", name, String::from(e))
}),*/
"gfx906" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx906_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx908" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx908_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx1010" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx1010_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx1011" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx1011_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx1012" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx1012_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx1030" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx1030_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx1031" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx1031_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
"gfx1032" => Program::create_and_build_from_binary(
&context,
&[include_bytes!("../resources/bin/gfx1032_kaspa-opencl.bin")],
"",
)
.unwrap_or_else(|e| panic!("{}::Program::create_and_build_from_binary failed: {}", name, e)),
other => {
panic!(
"{}: Found device {} without prebuilt binary. Trying to run without --opencl-amd-binary.",
name, other
);
match BINARY_DIR.get_file(format!("{}_kaspa-opencl.bin", device_name)) {
Some(binary) => {
Program::create_and_build_from_binary(&context, &[binary.contents()], "").unwrap_or_else(|e|{
warn!("{}::Program::create_and_build_from_source failed: {}. Reverting to compiling from source", name, e);
from_source(&context, &device, options).unwrap_or_else(|e| panic!("{}::Program::create_and_build_from_binary failed: {}", name, e))
})
},
None => {
warn!("Binary file not found for {}. Reverting to compiling from source.", device_name);
from_source(&context, &device, options).unwrap_or_else(|e| panic!("{}::Program::create_and_build_from_binary failed: {}", name, e))
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@ impl Opt {
}

if !self.kaspad_address.contains("://") {
let port = self.port();
self.kaspad_address = format!("grpc://{}:{}", self.kaspad_address, port);
let port_str = self.port().to_string();
let (kaspad, port) = match self.kaspad_address.contains(':') {
true => self.kaspad_address.split_once(':').expect("We checked for `:`"),
false => (self.kaspad_address.as_str(), port_str.as_str()),
};
self.kaspad_address = format!("grpc://{}:{}", kaspad, port);
}
log::info!("kaspad address: {}", self.kaspad_address);

Expand Down
Loading

0 comments on commit bfdca32

Please sign in to comment.