This is an automated email from the ASF dual-hosted git repository.
hcr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git
The following commit(s) were added to refs/heads/main by this push:
new 187dc4b77 feat: Make qdp-kernels build/link on Linux without nvcc by
providing stub symbols (#887)
187dc4b77 is described below
commit 187dc4b77afbda97e2780addf4052f711eaace08
Author: KUAN-HAO HUANG <[email protected]>
AuthorDate: Thu Jan 22 20:12:27 2026 +0800
feat: Make qdp-kernels build/link on Linux without nvcc by providing stub
symbols (#887)
* Make qdp-kernels build/link on Linux without nvcc by providing stub
symbolsy
* fix errors
* fix unsafe error
* fix errors
* fix thr test error
* fix errors
* fix error
* fix stupid error
* try to figure out this stupid error!
---
qdp/qdp-core/src/encoding/amplitude.rs | 4 +++
qdp/qdp-core/src/encoding/angle.rs | 24 ++++++++++--------
qdp/qdp-core/src/encoding/basis.rs | 4 +++
qdp/qdp-core/src/gpu/encodings/amplitude.rs | 4 +++
qdp/qdp-core/src/gpu/encodings/angle.rs | 4 +++
qdp/qdp-core/src/gpu/encodings/basis.rs | 4 +++
qdp/qdp-core/src/gpu/memory.rs | 5 ++++
qdp/qdp-core/src/gpu/pipeline.rs | 4 +++
qdp/qdp-core/src/lib.rs | 4 +++
qdp/qdp-kernels/build.rs | 13 +++++++++-
qdp/qdp-kernels/src/lib.rs | 38 ++++++++++++++++++++---------
qdp/qdp-kernels/tests/amplitude_encode.rs | 5 ++++
12 files changed, 90 insertions(+), 23 deletions(-)
diff --git a/qdp/qdp-core/src/encoding/amplitude.rs
b/qdp/qdp-core/src/encoding/amplitude.rs
index c308db33c..0606c0bd7 100644
--- a/qdp/qdp-core/src/encoding/amplitude.rs
+++ b/qdp/qdp-core/src/encoding/amplitude.rs
@@ -16,6 +16,10 @@
//! Amplitude encoding implementation.
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use std::ffi::c_void;
use cudarc::driver::{CudaSlice, DevicePtrMut};
diff --git a/qdp/qdp-core/src/encoding/angle.rs
b/qdp/qdp-core/src/encoding/angle.rs
index a9f5e5bc8..0eac78d48 100644
--- a/qdp/qdp-core/src/encoding/angle.rs
+++ b/qdp/qdp-core/src/encoding/angle.rs
@@ -16,6 +16,10 @@
//! Angle encoding implementation.
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use std::ffi::c_void;
use qdp_kernels::launch_angle_encode_batch;
@@ -103,22 +107,22 @@ impl ChunkEncoder for AngleEncoder {
}
}
- unsafe {
- crate::profile_scope!("GPU::BatchEncode");
- let ret = launch_angle_encode_batch(
+ crate::profile_scope!("GPU::BatchEncode");
+ let ret = unsafe {
+ launch_angle_encode_batch(
dev_ptr as *const f64,
state_ptr_offset,
samples_in_chunk,
state_len,
num_qubits as u32,
ctx.stream_compute.stream as *mut c_void,
- );
- if ret != 0 {
- return Err(MahoutError::KernelLaunch(format!(
- "Angle encode kernel error: {}",
- ret
- )));
- }
+ )
+ };
+ if ret != 0 {
+ return Err(MahoutError::KernelLaunch(format!(
+ "Angle encode kernel error: {}",
+ ret
+ )));
}
Ok(())
}
diff --git a/qdp/qdp-core/src/encoding/basis.rs
b/qdp/qdp-core/src/encoding/basis.rs
index 81750fa9a..b2c79a3d5 100644
--- a/qdp/qdp-core/src/encoding/basis.rs
+++ b/qdp/qdp-core/src/encoding/basis.rs
@@ -16,6 +16,10 @@
//! Basis encoding implementation.
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use std::ffi::c_void;
use cudarc::driver::{CudaSlice, DevicePtr};
diff --git a/qdp/qdp-core/src/gpu/encodings/amplitude.rs
b/qdp/qdp-core/src/gpu/encodings/amplitude.rs
index 0720cd619..c20f0103f 100644
--- a/qdp/qdp-core/src/gpu/encodings/amplitude.rs
+++ b/qdp/qdp-core/src/gpu/encodings/amplitude.rs
@@ -16,6 +16,10 @@
// Amplitude encoding: state injection with L2 normalization
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use std::sync::Arc;
use super::QuantumEncoder;
diff --git a/qdp/qdp-core/src/gpu/encodings/angle.rs
b/qdp/qdp-core/src/gpu/encodings/angle.rs
index aa4a347a0..44df2c810 100644
--- a/qdp/qdp-core/src/gpu/encodings/angle.rs
+++ b/qdp/qdp-core/src/gpu/encodings/angle.rs
@@ -16,6 +16,10 @@
// Angle encoding: map per-qubit angles to product state amplitudes.
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use super::QuantumEncoder;
#[cfg(target_os = "linux")]
use crate::error::cuda_error_to_string;
diff --git a/qdp/qdp-core/src/gpu/encodings/basis.rs
b/qdp/qdp-core/src/gpu/encodings/basis.rs
index b40d42d6f..2e6169ade 100644
--- a/qdp/qdp-core/src/gpu/encodings/basis.rs
+++ b/qdp/qdp-core/src/gpu/encodings/basis.rs
@@ -16,6 +16,10 @@
// Basis encoding: map integers to computational basis states
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use super::QuantumEncoder;
#[cfg(target_os = "linux")]
use crate::error::cuda_error_to_string;
diff --git a/qdp/qdp-core/src/gpu/memory.rs b/qdp/qdp-core/src/gpu/memory.rs
index 07ec86583..5ee59291a 100644
--- a/qdp/qdp-core/src/gpu/memory.rs
+++ b/qdp/qdp-core/src/gpu/memory.rs
@@ -13,6 +13,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+
+// Allow unused_unsafe: qdp_kernels functions are unsafe in CUDA builds but
safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use crate::error::{MahoutError, Result};
use cudarc::driver::{CudaDevice, CudaSlice, DevicePtr};
use qdp_kernels::{CuComplex, CuDoubleComplex};
diff --git a/qdp/qdp-core/src/gpu/pipeline.rs b/qdp/qdp-core/src/gpu/pipeline.rs
index 5acb7d32b..484cbc7cf 100644
--- a/qdp/qdp-core/src/gpu/pipeline.rs
+++ b/qdp/qdp-core/src/gpu/pipeline.rs
@@ -19,6 +19,10 @@
// Provides generic double-buffered execution for large data processing.
// Separates the "streaming mechanics" from the "kernel logic".
+// Allow unused_unsafe: CUDA FFI functions are unsafe in CUDA builds but safe
stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
use crate::error::{MahoutError, Result};
#[cfg(target_os = "linux")]
use crate::gpu::buffer_pool::{PinnedBufferHandle, PinnedBufferPool};
diff --git a/qdp/qdp-core/src/lib.rs b/qdp/qdp-core/src/lib.rs
index f0bedb73a..2b14f6c5b 100644
--- a/qdp/qdp-core/src/lib.rs
+++ b/qdp/qdp-core/src/lib.rs
@@ -14,6 +14,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// Allow unused_unsafe: CUDA FFI and kernel functions are unsafe in CUDA
builds but safe stubs in no-CUDA builds.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
pub mod dlpack;
#[cfg(target_os = "linux")]
mod encoding;
diff --git a/qdp/qdp-kernels/build.rs b/qdp/qdp-kernels/build.rs
index 546928d2f..093fbf71e 100644
--- a/qdp/qdp-kernels/build.rs
+++ b/qdp/qdp-kernels/build.rs
@@ -27,16 +27,27 @@ use std::env;
use std::process::Command;
fn main() {
+ // Let rustc know about our build-script-defined cfg flags (avoids
`unexpected_cfgs` warnings).
+ println!("cargo::rustc-check-cfg=cfg(qdp_no_cuda)");
+
// Tell Cargo to rerun this script if the kernel sources change
println!("cargo:rerun-if-changed=src/amplitude.cu");
println!("cargo:rerun-if-changed=src/basis.cu");
println!("cargo:rerun-if-changed=src/angle.cu");
+ println!("cargo:rerun-if-env-changed=QDP_NO_CUDA");
println!("cargo:rerun-if-changed=src/kernel_config.h");
// Check if CUDA is available by looking for nvcc
- let has_cuda = Command::new("nvcc").arg("--version").output().is_ok();
+ let force_no_cuda = env::var("QDP_NO_CUDA")
+ .map(|v| v == "1" || v.eq_ignore_ascii_case("true") ||
v.eq_ignore_ascii_case("yes"))
+ .unwrap_or(false);
+
+ let has_cuda = !force_no_cuda &&
Command::new("nvcc").arg("--version").output().is_ok();
if !has_cuda {
+ // Expose a cfg for conditional compilation of stub symbols on Linux.
+ // This allows qdp-kernels (and dependents) to link on Linux machines
without CUDA.
+ println!("cargo:rustc-cfg=qdp_no_cuda");
println!("cargo:warning=CUDA not found (nvcc not in PATH). Skipping
kernel compilation.");
println!("cargo:warning=This is expected on macOS or non-CUDA
environments.");
println!(
diff --git a/qdp/qdp-kernels/src/lib.rs b/qdp/qdp-kernels/src/lib.rs
index f1ebd351c..7bab4bf80 100644
--- a/qdp/qdp-kernels/src/lib.rs
+++ b/qdp/qdp-kernels/src/lib.rs
@@ -52,8 +52,8 @@ unsafe impl cudarc::driver::DeviceRepr for CuComplex {}
#[cfg(target_os = "linux")]
unsafe impl cudarc::driver::ValidAsZeroBits for CuComplex {}
-// CUDA kernel FFI (Linux only, dummy on other platforms)
-#[cfg(target_os = "linux")]
+// CUDA kernel FFI (Linux only; stubbed when built without nvcc/CUDA)
+#[cfg(all(target_os = "linux", not(qdp_no_cuda)))]
unsafe extern "C" {
/// Launch amplitude encoding kernel
/// Returns CUDA error code (0 = success)
@@ -190,8 +190,8 @@ unsafe extern "C" {
) -> i32;
}
-// Dummy implementation for non-Linux (allows compilation)
-#[cfg(not(target_os = "linux"))]
+// Dummy implementation for non-Linux and Linux builds without CUDA (allows
linking)
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_amplitude_encode(
_input_d: *const f64,
@@ -204,7 +204,7 @@ pub extern "C" fn launch_amplitude_encode(
999 // Error: CUDA unavailable
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_amplitude_encode_f32(
_input_d: *const f32,
@@ -217,7 +217,21 @@ pub extern "C" fn launch_amplitude_encode_f32(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
+#[unsafe(no_mangle)]
+pub extern "C" fn launch_amplitude_encode_batch(
+ _input_batch_d: *const f64,
+ _state_batch_d: *mut c_void,
+ _inv_norms_d: *const f64,
+ _num_samples: usize,
+ _input_len: usize,
+ _state_len: usize,
+ _stream: *mut c_void,
+) -> i32 {
+ 999
+}
+
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_l2_norm(
_input_d: *const f64,
@@ -228,7 +242,7 @@ pub extern "C" fn launch_l2_norm(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_l2_norm_batch(
_input_batch_d: *const f64,
@@ -240,7 +254,7 @@ pub extern "C" fn launch_l2_norm_batch(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn convert_state_to_float(
_input_state_d: *const CuDoubleComplex,
@@ -251,7 +265,7 @@ pub extern "C" fn convert_state_to_float(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_basis_encode(
_basis_index: usize,
@@ -262,7 +276,7 @@ pub extern "C" fn launch_basis_encode(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_basis_encode_batch(
_basis_indices_d: *const usize,
@@ -275,7 +289,7 @@ pub extern "C" fn launch_basis_encode_batch(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_angle_encode(
_angles_d: *const f64,
@@ -287,7 +301,7 @@ pub extern "C" fn launch_angle_encode(
999
}
-#[cfg(not(target_os = "linux"))]
+#[cfg(any(not(target_os = "linux"), qdp_no_cuda))]
#[unsafe(no_mangle)]
pub extern "C" fn launch_angle_encode_batch(
_angles_batch_d: *const f64,
diff --git a/qdp/qdp-kernels/tests/amplitude_encode.rs
b/qdp/qdp-kernels/tests/amplitude_encode.rs
index 0d69ca9ee..7ee181bfd 100644
--- a/qdp/qdp-kernels/tests/amplitude_encode.rs
+++ b/qdp/qdp-kernels/tests/amplitude_encode.rs
@@ -16,6 +16,11 @@
// Tests for amplitude encoding CUDA kernel
+// Allow unused_unsafe: in no-CUDA builds, stub functions are not unsafe,
+// but in CUDA builds, the extern "C" functions require unsafe blocks.
+// The compiler can't statically determine which path is taken.
+#![allow(unused_unsafe)]
+
#[cfg(target_os = "linux")]
use cudarc::driver::{CudaDevice, DevicePtr, DevicePtrMut};
#[cfg(target_os = "linux")]