This is an automated email from the ASF dual-hosted git repository.

guanmingchiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git

commit 509c28f6588caf8f6ab0153221ff0daa59fdbe40
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Mon Jan 5 19:32:04 2026 +0800

    [QDP] Fix benchmark to use batch encoding (#794)
---
 qdp/Cargo.lock                                | 23 +++++++++++++
 qdp/qdp-python/Cargo.toml                     |  1 +
 qdp/qdp-python/benchmark/benchmark_latency.py | 12 +++----
 qdp/qdp-python/src/lib.rs                     | 48 +++++++++++++++++++++++++++
 4 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/qdp/Cargo.lock b/qdp/Cargo.lock
index d65291be6..9e902660e 100644
--- a/qdp/Cargo.lock
+++ b/qdp/Cargo.lock
@@ -937,6 +937,22 @@ dependencies = [
  "libm",
 ]
 
+[[package]]
+name = "numpy"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7aac2e6a6e4468ffa092ad43c39b81c79196c2bb773b8db4085f695efe3bba17"
+dependencies = [
+ "libc",
+ "ndarray",
+ "num-complex",
+ "num-integer",
+ "num-traits",
+ "pyo3",
+ "pyo3-build-config",
+ "rustc-hash",
+]
+
 [[package]]
 name = "nvtx"
 version = "1.3.0"
@@ -1174,6 +1190,7 @@ dependencies = [
 name = "qdp-python"
 version = "0.1.0"
 dependencies = [
+ "numpy",
  "pyo3",
  "qdp-core",
 ]
@@ -1248,6 +1265,12 @@ version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
 
+[[package]]
+name = "rustc-hash"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+
 [[package]]
 name = "rustc_version"
 version = "0.4.1"
diff --git a/qdp/qdp-python/Cargo.toml b/qdp/qdp-python/Cargo.toml
index 8232f822b..d00373bc0 100644
--- a/qdp/qdp-python/Cargo.toml
+++ b/qdp/qdp-python/Cargo.toml
@@ -9,6 +9,7 @@ crate-type = ["cdylib"]
 
 [dependencies]
 pyo3 = { version = "0.27", features = ["extension-module"] }
+numpy = "0.27"
 qdp-core = { path = "../qdp-core" }
 
 [features]
diff --git a/qdp/qdp-python/benchmark/benchmark_latency.py 
b/qdp/qdp-python/benchmark/benchmark_latency.py
index bd6903f62..b1c776d1e 100644
--- a/qdp/qdp-python/benchmark/benchmark_latency.py
+++ b/qdp/qdp-python/benchmark/benchmark_latency.py
@@ -129,18 +129,16 @@ def run_mahout(num_qubits: int, total_batches: int, 
batch_size: int, prefetch: i
         print(f"[Mahout] Init failed: {exc}")
         return 0.0, 0.0
 
+    vector_len = 1 << num_qubits
     sync_cuda()
     start = time.perf_counter()
     processed = 0
 
-    for batch in prefetched_batches(
-        total_batches, batch_size, 1 << num_qubits, prefetch
-    ):
+    for batch in prefetched_batches(total_batches, batch_size, vector_len, 
prefetch):
         normalized = normalize_batch(batch)
-        for sample in normalized:
-            qtensor = engine.encode(sample.tolist(), num_qubits, "amplitude")
-            _ = torch.utils.dlpack.from_dlpack(qtensor)
-            processed += 1
+        qtensor = engine.encode_batch(normalized, num_qubits, "amplitude")
+        _ = torch.utils.dlpack.from_dlpack(qtensor)
+        processed += normalized.shape[0]
 
     sync_cuda()
     duration = time.perf_counter() - start
diff --git a/qdp/qdp-python/src/lib.rs b/qdp/qdp-python/src/lib.rs
index 153674d83..1dc60da70 100644
--- a/qdp/qdp-python/src/lib.rs
+++ b/qdp/qdp-python/src/lib.rs
@@ -14,6 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use numpy::{PyReadonlyArray2, PyUntypedArrayMethods};
 use pyo3::exceptions::PyRuntimeError;
 use pyo3::ffi;
 use pyo3::prelude::*;
@@ -246,6 +247,53 @@ impl QdpEngine {
         })
     }
 
+    /// Encode a batch of samples from NumPy array (zero-copy, most efficient)
+    ///
+    /// Args:
+    ///     batch_data: 2D NumPy array of shape [num_samples, sample_size] 
with dtype float64
+    ///     num_qubits: Number of qubits for encoding
+    ///     encoding_method: Encoding strategy ("amplitude", "angle", or 
"basis")
+    ///
+    /// Returns:
+    ///     QuantumTensor: DLPack tensor containing all encoded states
+    ///         Shape: [num_samples, 2^num_qubits]
+    ///
+    /// Example:
+    ///     >>> engine = QdpEngine(device_id=0)
+    ///     >>> batch = np.random.randn(64, 4).astype(np.float64)
+    ///     >>> qtensor = engine.encode_batch(batch, 2, "amplitude")
+    ///     >>> torch_tensor = torch.from_dlpack(qtensor)  # Shape: [64, 4]
+    fn encode_batch(
+        &self,
+        batch_data: PyReadonlyArray2<f64>,
+        num_qubits: usize,
+        encoding_method: &str,
+    ) -> PyResult<QuantumTensor> {
+        let shape = batch_data.shape();
+        let num_samples = shape[0];
+        let sample_size = shape[1];
+
+        // Get contiguous slice from numpy array (zero-copy if already 
contiguous)
+        let data_slice = batch_data
+            .as_slice()
+            .map_err(|_| PyRuntimeError::new_err("NumPy array must be 
contiguous (C-order)"))?;
+
+        let ptr = self
+            .engine
+            .encode_batch(
+                data_slice,
+                num_samples,
+                sample_size,
+                num_qubits,
+                encoding_method,
+            )
+            .map_err(|e| PyRuntimeError::new_err(format!("Batch encoding 
failed: {}", e)))?;
+        Ok(QuantumTensor {
+            ptr,
+            consumed: false,
+        })
+    }
+
     /// Encode from PyTorch Tensor
     ///
     /// Args:

Reply via email to