use pandrs::error::Result;
#[cfg(feature = "cuda")]
use pandrs::gpu::{get_gpu_manager, init_gpu, GpuConfig};
use pandrs::DataFrame;
use pandrs::Series;
#[cfg(feature = "cuda")]
use std::collections::HashMap;
#[cfg(feature = "cuda")]
use std::time::Instant;
#[cfg(feature = "cuda")]
use pandrs::DataFrameGpuExt;
#[cfg(feature = "cuda")]
fn main() -> Result<()> {
println!("PandRS GPU-accelerated DataFrame API Example");
println!("-------------------------------------------");
let device_status = init_gpu()?;
println!("\nGPU Device Status:");
println!(" Available: {}", device_status.available);
if device_status.available {
println!(
" Device Name: {}",
device_status
.device_name
.unwrap_or_else(|| "Unknown".to_string())
);
println!(
" CUDA Version: {}",
device_status
.cuda_version
.unwrap_or_else(|| "Unknown".to_string())
);
println!(
" Total Memory: {} MB",
device_status.total_memory.unwrap_or(0) / (1024 * 1024)
);
println!(
" Free Memory: {} MB",
device_status.free_memory.unwrap_or(0) / (1024 * 1024)
);
} else {
println!(" No CUDA-compatible GPU available. Using CPU fallback.");
}
let mut df = create_sample_dataframe(10_000)?;
println!(
"\nCreated sample DataFrame with {} rows and {} columns",
df.row_count(),
df.column_count()
);
println!("\nFirst 5 rows:");
println!("{}", df.head(5)?);
benchmark_correlation(&df)?;
benchmark_linear_regression(&df)?;
benchmark_pca(&df)?;
benchmark_kmeans(&df)?;
benchmark_describe(&df)?;
Ok(())
}
#[allow(dead_code)]
fn create_sample_dataframe(size: usize) -> Result<DataFrame> {
let mut x1 = Vec::with_capacity(size);
let mut x2 = Vec::with_capacity(size);
let mut x3 = Vec::with_capacity(size);
let mut x4 = Vec::with_capacity(size);
let mut y = Vec::with_capacity(size);
for i in 0..size {
let x1_val = (i % 100) as f64 / 100.0;
let x2_val = ((i * 2) % 100) as f64 / 100.0;
let x3_val = ((i * 3) % 100) as f64 / 100.0;
let x4_val = ((i * 5) % 100) as f64 / 100.0;
let y_val = 2.0 * x1_val + 1.5 * x2_val - 0.5 * x3_val
+ 3.0 * x4_val
+ 0.1 * (rand::random::<f64>() - 0.5);
x1.push(x1_val);
x2.push(x2_val);
x3.push(x3_val);
x4.push(x4_val);
y.push(y_val);
}
let mut df = DataFrame::new();
df.add_column("x1".to_string(), Series::new(x1, Some("x1".to_string()))?)?;
df.add_column("x2".to_string(), Series::new(x2, Some("x2".to_string()))?)?;
df.add_column("x3".to_string(), Series::new(x3, Some("x3".to_string()))?)?;
df.add_column("x4".to_string(), Series::new(x4, Some("x4".to_string()))?)?;
df.add_column("y".to_string(), Series::new(y, Some("y".to_string()))?)?;
Ok(df)
}
#[cfg(feature = "cuda")]
fn print_matrix_preview(matrix: &ndarray::Array2<f64>, max_rows: usize, max_cols: usize) {
let (rows, cols) = matrix.dim();
let rows_to_show = rows.min(max_rows);
let cols_to_show = cols.min(max_cols);
for i in 0..rows_to_show {
for j in 0..cols_to_show {
print!("{:.4} ", matrix[[i, j]]);
}
print!("...\n");
}
println!("...");
}
#[cfg(feature = "cuda")]
fn benchmark_correlation(df: &DataFrame) -> Result<()> {
println!("\nCorrelation Matrix Benchmark");
println!("----------------------------");
let cpu_start = Instant::now();
let cpu_corr = df.corr()?;
let cpu_duration = cpu_start.elapsed().as_millis();
println!("\nStandard correlation (CPU):");
println!(" CPU Time: {} ms", cpu_duration);
print_matrix_preview(&cpu_corr, 5, 5);
let gpu_start = Instant::now();
let feature_cols = ["x1", "x2", "x3", "x4"];
let gpu_corr = df.gpu_corr(&feature_cols)?;
let gpu_duration = gpu_start.elapsed().as_millis();
println!("\nGPU-accelerated correlation:");
println!(" GPU Time: {} ms", gpu_duration);
print_matrix_preview(&gpu_corr, 5, 5);
let speedup = if gpu_duration > 0 {
cpu_duration as f64 / gpu_duration as f64
} else {
0.0
};
println!("\nSpeedup: {:.2}x", speedup);
Ok(())
}
#[cfg(feature = "cuda")]
fn benchmark_linear_regression(df: &DataFrame) -> Result<()> {
println!("\nLinear Regression Benchmark");
println!("--------------------------");
let cpu_start = Instant::now();
let cpu_model = pandrs::stats::linear_regression(df, "y", &["x1", "x2", "x3", "x4"])?;
let cpu_duration = cpu_start.elapsed().as_millis();
println!("\nStandard linear regression (CPU):");
println!(" CPU Time: {} ms", cpu_duration);
println!(" Intercept: {:.4}", cpu_model.intercept);
println!(
" Coefficients: [{:.4}, {:.4}, {:.4}, {:.4}]",
cpu_model.coefficients[0],
cpu_model.coefficients[1],
cpu_model.coefficients[2],
cpu_model.coefficients[3]
);
println!(" R²: {:.4}", cpu_model.r_squared);
let gpu_start = Instant::now();
let feature_cols = ["x1", "x2", "x3", "x4"];
let gpu_model = df.gpu_linear_regression("y", &feature_cols)?;
let gpu_duration = gpu_start.elapsed().as_millis();
println!("\nGPU-accelerated linear regression:");
println!(" GPU Time: {} ms", gpu_duration);
println!(" Intercept: {:.4}", gpu_model.intercept);
println!(
" Coefficients: [{:.4}, {:.4}, {:.4}, {:.4}]",
gpu_model.coefficients["x1"],
gpu_model.coefficients["x2"],
gpu_model.coefficients["x3"],
gpu_model.coefficients["x4"]
);
println!(" R²: {:.4}", gpu_model.r_squared);
let speedup = if gpu_duration > 0 {
cpu_duration as f64 / gpu_duration as f64
} else {
0.0
};
println!("\nSpeedup: {:.2}x", speedup);
Ok(())
}
#[cfg(feature = "cuda")]
fn benchmark_pca(df: &DataFrame) -> Result<()> {
println!("\nPrincipal Component Analysis (PCA) Benchmark");
println!("-------------------------------------------");
let cpu_start = Instant::now();
let feature_cols = ["x1", "x2", "x3", "x4"];
let n_components = 2;
let opt_df = pandrs::OptimizedDataFrame::from_dataframe(df)?;
let (components, variance, _) = opt_df.pca(
&feature_cols
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>(),
n_components,
)?;
let cpu_duration = cpu_start.elapsed().as_millis();
println!("\nStandard PCA (CPU):");
println!(" CPU Time: {} ms", cpu_duration);
println!(
" Explained variance: [{:.4}, {:.4}]",
variance[0], variance[1]
);
let gpu_start = Instant::now();
let (pca_df, explained_variance) = df.gpu_pca(&feature_cols, n_components)?;
let gpu_duration = gpu_start.elapsed().as_millis();
println!("\nGPU-accelerated PCA:");
println!(" GPU Time: {} ms", gpu_duration);
println!(
" Explained variance: [{:.4}, {:.4}]",
explained_variance[0], explained_variance[1]
);
println!(" First few rows of transformed data:");
println!("{}", pca_df.head(5)?);
let speedup = if gpu_duration > 0 {
cpu_duration as f64 / gpu_duration as f64
} else {
0.0
};
println!("\nSpeedup: {:.2}x", speedup);
Ok(())
}
#[cfg(feature = "cuda")]
fn benchmark_kmeans(df: &DataFrame) -> Result<()> {
println!("\nK-means Clustering Benchmark");
println!("---------------------------");
let cpu_start = Instant::now();
let feature_cols = ["x1", "x2", "x3", "x4"];
let k = 3;
let max_iter = 100;
let opt_df = pandrs::OptimizedDataFrame::from_dataframe(df)?;
let result = pandrs::ml::clustering::kmeans(
&opt_df,
&feature_cols
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>(),
k,
max_iter,
None,
)?;
let cpu_duration = cpu_start.elapsed().as_millis();
println!("\nStandard k-means (CPU):");
println!(" CPU Time: {} ms", cpu_duration);
println!(" Number of iterations: {}", result.n_iter);
println!(" Inertia: {:.4}", result.inertia);
let gpu_start = Instant::now();
let (centroids, labels, inertia) = df.gpu_kmeans(&feature_cols, k, max_iter)?;
let gpu_duration = gpu_start.elapsed().as_millis();
println!("\nGPU-accelerated k-means:");
println!(" GPU Time: {} ms", gpu_duration);
println!(" Inertia: {:.4}", inertia);
println!(" Centroids shape: {:?}", centroids.dim());
let mut cluster_sizes = HashMap::new();
for &label in labels.iter() {
*cluster_sizes.entry(label).or_insert(0) += 1;
}
println!(" Cluster sizes:");
for (cluster, size) in cluster_sizes.iter() {
println!(" Cluster {}: {} samples", cluster, size);
}
let speedup = if gpu_duration > 0 {
cpu_duration as f64 / gpu_duration as f64
} else {
0.0
};
println!("\nSpeedup: {:.2}x", speedup);
Ok(())
}
#[cfg(feature = "cuda")]
fn benchmark_describe(df: &DataFrame) -> Result<()> {
println!("\nDescriptive Statistics Benchmark");
println!("--------------------------------");
let cpu_start = Instant::now();
let cpu_stats = df.describe()?;
let cpu_duration = cpu_start.elapsed().as_millis();
println!("\nStandard describe (CPU):");
println!(" CPU Time: {} ms", cpu_duration);
println!("{}", cpu_stats);
let gpu_start = Instant::now();
let gpu_stats = df.gpu_describe("y")?;
let gpu_duration = gpu_start.elapsed().as_millis();
println!("\nGPU-accelerated describe for column 'y':");
println!(" GPU Time: {} ms", gpu_duration);
println!(" Count: {}", gpu_stats.count);
println!(" Mean: {:.4}", gpu_stats.mean);
println!(" Std: {:.4}", gpu_stats.std);
println!(" Min: {:.4}", gpu_stats.min);
println!(" 25%: {:.4}", gpu_stats.q1);
println!(" 50%: {:.4}", gpu_stats.median);
println!(" 75%: {:.4}", gpu_stats.q3);
println!(" Max: {:.4}", gpu_stats.max);
let cpu_per_column = cpu_duration as f64 / df.column_count() as f64;
let speedup = if gpu_duration > 0 {
cpu_per_column / gpu_duration as f64
} else {
0.0
};
println!("\nSpeedup (per column): {:.2}x", speedup);
Ok(())
}
#[cfg(not(feature = "cuda"))]
fn main() {
println!("This example requires the \"cuda\" feature flag to be enabled.");
println!("Please recompile with:");
println!(" cargo run --example gpu_dataframe_api_example --features \"cuda\"");
}