Skip to content

Commit bfdca32

Browse files
committed
Doesn't start the miner if no workers available + added fallback for amd binaries
1 parent 8bf16e6 commit bfdca32

File tree

9 files changed

+160
-171
lines changed

9 files changed

+160
-171
lines changed

.github/workflows/deploy.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ jobs:
4646
uses: Jimver/[email protected]
4747
with:
4848
cuda: '11.5.1'
49-
method: 'network'
50-
sub-packages: '["nvcc", "cudart"]'
49+
#method: 'local'
50+
#sub-packages: '["nvcc", "cudart"]'
5151

5252
- name: Build on Linux GNU
5353
if: matrix.os == 'ubuntu-18.04'

Cargo.lock

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/cuda/src/lib.rs

+65-64
Original file line numberDiff line numberDiff line change
@@ -49,81 +49,82 @@ impl Plugin for CudaPlugin {
4949
}
5050

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

5555
self._enabled = !opts.cuda_disable;
56+
if self._enabled {
57+
let gpus: Vec<u16> = match &opts.cuda_device {
58+
Some(devices) => devices.clone(),
59+
None => {
60+
let gpu_count = Device::num_devices().unwrap() as u16;
61+
(0..gpu_count).collect()
62+
}
63+
};
64+
65+
// if any of cuda_lock_core_clocks / cuda_lock_mem_clocks / cuda_power_limit is valid, init nvml and try to apply
66+
if opts.cuda_lock_core_clocks.is_some()
67+
|| opts.cuda_lock_mem_clocks.is_some()
68+
|| opts.cuda_power_limits.is_some()
69+
{
70+
for i in 0..gpus.len() {
71+
let lock_mem_clock: Option<u32> = match &opts.cuda_lock_mem_clocks {
72+
Some(mem_clocks) if i < mem_clocks.len() => Some(mem_clocks[i]),
73+
Some(mem_clocks) if !mem_clocks.is_empty() => Some(*mem_clocks.last().unwrap()),
74+
_ => None,
75+
};
5676

57-
let gpus: Vec<u16> = match &opts.cuda_device {
58-
Some(devices) => devices.clone(),
59-
None => {
60-
let gpu_count = Device::num_devices().unwrap() as u16;
61-
(0..gpu_count).collect()
62-
}
63-
};
64-
65-
// if any of cuda_lock_core_clocks / cuda_lock_mem_clocks / cuda_power_limit is valid, init nvml and try to apply
66-
if opts.cuda_lock_core_clocks.is_some()
67-
|| opts.cuda_lock_mem_clocks.is_some()
68-
|| opts.cuda_power_limits.is_some()
69-
{
70-
for i in 0..gpus.len() {
71-
let lock_mem_clock: Option<u32> = match &opts.cuda_lock_mem_clocks {
72-
Some(mem_clocks) if i < mem_clocks.len() => Some(mem_clocks[i]),
73-
Some(mem_clocks) if !mem_clocks.is_empty() => Some(*mem_clocks.last().unwrap()),
74-
_ => None,
75-
};
76-
77-
let lock_core_clock: Option<u32> = match &opts.cuda_lock_core_clocks {
78-
Some(core_clocks) if i < core_clocks.len() => Some(core_clocks[i]),
79-
Some(core_clocks) if !core_clocks.is_empty() => Some(*core_clocks.last().unwrap()),
80-
_ => None,
81-
};
82-
83-
let power_limit: Option<u32> = match &opts.cuda_power_limits {
84-
Some(power_limits) if i < power_limits.len() => Some(power_limits[i]),
85-
Some(power_limits) if !power_limits.is_empty() => Some(*power_limits.last().unwrap()),
86-
_ => None,
87-
};
88-
89-
let mut nvml_device: NvmlDevice = self.nvml_instance.device_by_index(gpus[i] as u32)?;
90-
91-
if let Some(lmc) = lock_mem_clock {
92-
match nvml_device.set_mem_locked_clocks(lmc, lmc) {
93-
Err(e) => error!("set mem locked clocks {:?}", e),
94-
_ => info!("GPU #{} #{} lock mem clock at {} Mhz", i, &nvml_device.name()?, &lmc),
77+
let lock_core_clock: Option<u32> = match &opts.cuda_lock_core_clocks {
78+
Some(core_clocks) if i < core_clocks.len() => Some(core_clocks[i]),
79+
Some(core_clocks) if !core_clocks.is_empty() => Some(*core_clocks.last().unwrap()),
80+
_ => None,
9581
};
96-
}
9782

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

105-
if let Some(pl) = power_limit {
106-
match nvml_device.set_power_management_limit(pl * 1000) {
107-
Err(e) => error!("set power limit {:?}", e),
108-
_ => info!("GPU #{} #{} power limit at {} W", i, &nvml_device.name()?, &pl),
89+
let mut nvml_device: NvmlDevice = self.nvml_instance.device_by_index(gpus[i] as u32)?;
90+
91+
if let Some(lmc) = lock_mem_clock {
92+
match nvml_device.set_mem_locked_clocks(lmc, lmc) {
93+
Err(e) => error!("set mem locked clocks {:?}", e),
94+
_ => info!("GPU #{} #{} lock mem clock at {} Mhz", i, &nvml_device.name()?, &lmc),
95+
};
96+
}
97+
98+
if let Some(lcc) = lock_core_clock {
99+
match nvml_device.set_gpu_locked_clocks(lcc, lcc) {
100+
Err(e) => error!("set gpu locked clocks {:?}", e),
101+
_ => info!("GPU #{} #{} lock core clock at {} Mhz", i, &nvml_device.name()?, &lcc),
102+
};
109103
};
110-
};
104+
105+
if let Some(pl) = power_limit {
106+
match nvml_device.set_power_management_limit(pl * 1000) {
107+
Err(e) => error!("set power limit {:?}", e),
108+
_ => info!("GPU #{} #{} power limit at {} W", i, &nvml_device.name()?, &pl),
109+
};
110+
};
111+
}
111112
}
112-
}
113113

114-
self.specs = (0..gpus.len())
115-
.map(|i| CudaWorkerSpec {
116-
device_id: gpus[i] as u32,
117-
workload: match &opts.cuda_workload {
118-
Some(workload) if i < workload.len() => workload[i],
119-
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
120-
_ => DEFAULT_WORKLOAD_SCALE,
121-
},
122-
is_absolute: opts.cuda_workload_absolute,
123-
blocking_sync: !opts.cuda_no_blocking_sync,
124-
})
125-
.collect();
126-
Ok(())
114+
self.specs = (0..gpus.len())
115+
.map(|i| CudaWorkerSpec {
116+
device_id: gpus[i] as u32,
117+
workload: match &opts.cuda_workload {
118+
Some(workload) if i < workload.len() => workload[i],
119+
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
120+
_ => DEFAULT_WORKLOAD_SCALE,
121+
},
122+
is_absolute: opts.cuda_workload_absolute,
123+
blocking_sync: !opts.cuda_no_blocking_sync,
124+
})
125+
.collect();
126+
}
127+
Ok(self.specs.len())
127128
}
128129
}
129130

plugins/opencl/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ env_logger = "0.9"
1111
opencl3 = {version = "0.6", features = ["CL_VERSION_2_1", "CL_VERSION_2_2", "CL_VERSION_3_0"]}
1212
log = "0.4"
1313
rand = "0.8"
14+
include_dir = "0.7"
1415

1516
[lib]
1617
crate-type = ["cdylib"]

plugins/opencl/src/lib.rs

+34-33
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Plugin for OpenCLPlugin {
4545
}
4646

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

5151
self._enabled = opts.opencl_enable;
@@ -77,38 +77,39 @@ impl Plugin for OpenCLPlugin {
7777
}
7878
None => &platforms[0],
7979
};
80-
info!(
81-
"Chose to mine on {}: {}.",
82-
&_platform.vendor().unwrap_or_else(|_| "Unk".into()),
83-
&_platform.name().unwrap_or_else(|_| "Unk".into())
84-
);
85-
86-
let device_ids = _platform.get_devices(CL_DEVICE_TYPE_ALL).unwrap();
87-
let gpus = match opts.opencl_device {
88-
Some(dev) => {
89-
self._enabled = true;
90-
dev.iter().map(|d| device_ids[*d as usize]).collect::<Vec<cl_device_id>>()
91-
}
92-
None => device_ids,
93-
};
94-
95-
self.specs = (0..gpus.len())
96-
.map(|i| OpenCLWorkerSpec {
97-
_platform: *_platform,
98-
device_id: Device::new(gpus[i]),
99-
workload: match &opts.opencl_workload {
100-
Some(workload) if i < workload.len() => workload[i],
101-
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
102-
_ => DEFAULT_WORKLOAD_SCALE,
103-
},
104-
is_absolute: opts.opencl_workload_absolute,
105-
experimental_amd: opts.experimental_amd,
106-
use_amd_binary: !opts.opencl_no_amd_binary,
107-
random: opts.nonce_gen,
108-
})
109-
.collect();
110-
111-
Ok(())
80+
if self._enabled {
81+
info!(
82+
"Chose to mine on {}: {}.",
83+
&_platform.vendor().unwrap_or_else(|_| "Unk".into()),
84+
&_platform.name().unwrap_or_else(|_| "Unk".into())
85+
);
86+
87+
let device_ids = _platform.get_devices(CL_DEVICE_TYPE_ALL).unwrap();
88+
let gpus = match opts.opencl_device {
89+
Some(dev) => {
90+
self._enabled = true;
91+
dev.iter().map(|d| device_ids[*d as usize]).collect::<Vec<cl_device_id>>()
92+
}
93+
None => device_ids,
94+
};
95+
96+
self.specs = (0..gpus.len())
97+
.map(|i| OpenCLWorkerSpec {
98+
_platform: *_platform,
99+
device_id: Device::new(gpus[i]),
100+
workload: match &opts.opencl_workload {
101+
Some(workload) if i < workload.len() => workload[i],
102+
Some(workload) if !workload.is_empty() => *workload.last().unwrap(),
103+
_ => DEFAULT_WORKLOAD_SCALE,
104+
},
105+
is_absolute: opts.opencl_workload_absolute,
106+
experimental_amd: opts.experimental_amd,
107+
use_amd_binary: !opts.opencl_no_amd_binary,
108+
random: opts.nonce_gen,
109+
})
110+
.collect();
111+
}
112+
Ok(self.specs.len())
112113
}
113114
}
114115

plugins/opencl/src/worker.rs

+17-64
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::cli::NonceGenEnum;
22
use crate::Error;
3+
use include_dir::{include_dir, Dir};
34
use kaspa_miner::xoshiro256starstar::Xoshiro256StarStar;
45
use kaspa_miner::Worker;
5-
use log::info;
6+
use log::{info, warn};
67
use opencl3::command_queue::{CommandQueue, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE};
78
use opencl3::context::Context;
89
use opencl3::device::Device;
@@ -18,6 +19,7 @@ use std::ffi::c_void;
1819
use std::ptr;
1920
use std::sync::Arc;
2021

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

2325
pub struct OpenCLGPUWorker {
@@ -197,70 +199,21 @@ impl OpenCLGPUWorker {
197199

198200
let program = match use_binary {
199201
true => {
200-
let device_name = device.name().unwrap_or_else(|_| "Unknown".into()).to_lowercase();
202+
let mut device_name = device.name().unwrap_or_else(|_| "Unknown".into()).to_lowercase();
203+
if device_name.contains(':') {
204+
device_name = device_name.split_once(':').expect("We checked for `:`").0.to_string();
205+
}
201206
info!("{}: Looking for binary for {}", name, device_name);
202-
match device_name.as_str() {
203-
/*"ellesmere" => Program::create_and_build_from_binary(
204-
&context,
205-
&[include_bytes!("../resources/bin/ellesmere_kaspa-opencl.bin")],
206-
"",
207-
)
208-
.unwrap_or_else(|e| {
209-
panic!("{}::Program::create_and_build_from_binary failed: {}", name, String::from(e))
210-
}),*/
211-
"gfx906" => Program::create_and_build_from_binary(
212-
&context,
213-
&[include_bytes!("../resources/bin/gfx906_kaspa-opencl.bin")],
214-
"",
215-
)
216-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
217-
"gfx908" => Program::create_and_build_from_binary(
218-
&context,
219-
&[include_bytes!("../resources/bin/gfx908_kaspa-opencl.bin")],
220-
"",
221-
)
222-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
223-
"gfx1010" => Program::create_and_build_from_binary(
224-
&context,
225-
&[include_bytes!("../resources/bin/gfx1010_kaspa-opencl.bin")],
226-
"",
227-
)
228-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
229-
"gfx1011" => Program::create_and_build_from_binary(
230-
&context,
231-
&[include_bytes!("../resources/bin/gfx1011_kaspa-opencl.bin")],
232-
"",
233-
)
234-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
235-
"gfx1012" => Program::create_and_build_from_binary(
236-
&context,
237-
&[include_bytes!("../resources/bin/gfx1012_kaspa-opencl.bin")],
238-
"",
239-
)
240-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
241-
"gfx1030" => Program::create_and_build_from_binary(
242-
&context,
243-
&[include_bytes!("../resources/bin/gfx1030_kaspa-opencl.bin")],
244-
"",
245-
)
246-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
247-
"gfx1031" => Program::create_and_build_from_binary(
248-
&context,
249-
&[include_bytes!("../resources/bin/gfx1031_kaspa-opencl.bin")],
250-
"",
251-
)
252-
.unwrap_or_else(|_| panic!("{}::Program::create_and_build_from_binary failed", name)),
253-
"gfx1032" => Program::create_and_build_from_binary(
254-
&context,
255-
&[include_bytes!("../resources/bin/gfx1032_kaspa-opencl.bin")],
256-
"",
257-
)
258-
.unwrap_or_else(|e| panic!("{}::Program::create_and_build_from_binary failed: {}", name, e)),
259-
other => {
260-
panic!(
261-
"{}: Found device {} without prebuilt binary. Trying to run without --opencl-amd-binary.",
262-
name, other
263-
);
207+
match BINARY_DIR.get_file(format!("{}_kaspa-opencl.bin", device_name)) {
208+
Some(binary) => {
209+
Program::create_and_build_from_binary(&context, &[binary.contents()], "").unwrap_or_else(|e|{
210+
warn!("{}::Program::create_and_build_from_source failed: {}. Reverting to compiling from source", name, e);
211+
from_source(&context, &device, options).unwrap_or_else(|e| panic!("{}::Program::create_and_build_from_binary failed: {}", name, e))
212+
})
213+
},
214+
None => {
215+
warn!("Binary file not found for {}. Reverting to compiling from source.", device_name);
216+
from_source(&context, &device, options).unwrap_or_else(|e| panic!("{}::Program::create_and_build_from_binary failed: {}", name, e))
264217
}
265218
}
266219
}

src/cli.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,12 @@ impl Opt {
7070
}
7171

7272
if !self.kaspad_address.contains("://") {
73-
let port = self.port();
74-
self.kaspad_address = format!("grpc://{}:{}", self.kaspad_address, port);
73+
let port_str = self.port().to_string();
74+
let (kaspad, port) = match self.kaspad_address.contains(':') {
75+
true => self.kaspad_address.split_once(':').expect("We checked for `:`"),
76+
false => (self.kaspad_address.as_str(), port_str.as_str()),
77+
};
78+
self.kaspad_address = format!("grpc://{}:{}", kaspad, port);
7579
}
7680
log::info!("kaspad address: {}", self.kaspad_address);
7781

0 commit comments

Comments
 (0)