# CUDA benefit diagnostic _Generated by `benchmarks/cross_binding/cuda_diagnostic.py`. The CUDA (cuBLAS) backend now BUILDS (`cuda-on` preset) and is verified bit-identical to the CPU reference on GPU (rmse_rel = 0 on pcr/pls/mb_pls/gpr_pls, RTX 4090/5090); this report prioritises **where it pays off**._ ## Method Proxy = BLAS+OpenMP vs native-scalar speedup at the largest measured n×p (BLAS and CUDA accelerate the same GEMM/GEMV path). An absolute floor is applied FIRST: any op under 1 ms is `not_applicable` regardless of its (noisy) speedup — CUDA launch + host↔device copy overhead alone exceeds it. Above the floor: `benefits` = speedup ≥ 1.4 and (grows with size or already ≥ 5 ms); `marginal` = speedup ≥ 1.2; else `not_applicable`. The backend is built + correctness-verified; a full live GPU timing sweep (which sizes actually win, given launch + host↔device copy overhead) is the remaining refinement — treat the buckets below as the prioritisation for it. Structurally GEMM-bound core TUs: `aom_selection.cpp`, `gpr_pls.cpp`, `kernel_pls.cpp`, `mb_pls.cpp`, `model.cpp`, `multiblock_extensions.cpp`. ## ✅ Would benefit from CUDA (2) | method | size | native ms | blas+omp ms | speedup | grows w/ size | |---|---|---|---|---|---| | `bipls_select` | 250x50 | 11.285 | 7.25 | 1.56× | yes | | `pls_qda` | 250x50 | 6.007 | 3.98 | 1.51× | yes | ## 🟡 Marginal / size-dependent (7) | method | size | native ms | blas+omp ms | speedup | grows w/ size | |---|---|---|---|---|---| | `on_pls` | 250x50 | 6.681 | 4.352 | 1.54× | no | | `variable_select_coef` | 250x50 | 4.04 | 2.632 | 1.53× | no | | `sparse_pls_da` | 250x50 | 4.024 | 2.907 | 1.38× | no | | `boosting_pls` | 250x50 | 3.29 | 2.639 | 1.25× | no | | `pp_wavelet_svd` | 250x50 | 5.975 | 4.861 | 1.23× | no | | `fused_sparse_pls` | 250x50 | 3.445 | 2.857 | 1.21× | yes | | `pls_diagnostic_dmodx` | 250x50 | 3.822 | 3.167 | 1.21× | yes | ## ⛔ Not applicable (CUDA would be slower) (168) | method | size | native ms | blas+omp ms | speedup | grows w/ size | |---|---|---|---|---|---| | `pp_snv` | 250x50 | 0.041 | 0.013 | 3.15× | no | | `aug_scatter_sim` | 50x250 | 0.008 | 0.003 | 2.67× | no | | `pp_msc` | 250x50 | 0.045 | 0.019 | 2.37× | yes | | `pp_crop` | 250x50 | 0.008 | 0.004 | 2.0× | yes | | `pp_resample` | 250x50 | 0.085 | 0.043 | 1.98× | no | | `pp_lsnv` | 250x50 | 0.207 | 0.128 | 1.62× | no | | `band_mask` | 250x50 | 0.017 | 0.011 | 1.55× | no | | `split_bsgk` | 250x50 | 0.003 | 0.002 | 1.5× | no | | `local_clip` | 250x50 | 0.077 | 0.053 | 1.45× | no | | `pp_norris_williams` | 250x50 | 0.089 | 0.062 | 1.44× | no | | `pp_pct_to_frac` | 250x50 | 0.007 | 0.005 | 1.4× | no | | `aug_gaussian_noise` | 250x50 | 0.152 | 0.109 | 1.39× | no | | `pp_wavelet_features` | 250x50 | 0.132 | 0.095 | 1.39× | no | | `pp_log` | 250x50 | 0.098 | 0.073 | 1.34× | no | | `aug_edge_curvature` | 250x50 | 0.208 | 0.159 | 1.31× | no | | `aug_local_mixup` | 50x250 | 0.43 | 0.331 | 1.3× | no | | `pp_area` | 250x50 | 0.005 | 0.004 | 1.25× | no | | `wavelength_shift` | 250x50 | 0.105 | 0.084 | 1.25× | yes | | `aug_instrument_broaden` | 50x250 | 0.022 | 0.018 | 1.22× | no | | `recursive_pls` | 250x50 | 5.833 | 4.921 | 1.19× | no | | `pp_kbins_disc` | 250x50 | 0.154 | 0.13 | 1.18× | no | | `pp_wavelet_denoise` | 250x50 | 0.144 | 0.122 | 1.18× | no | | `aug_spline_x_perturbations` | 250x50 | 1.249 | 1.069 | 1.17× | no | | `pp_second_derivative` | 250x50 | 0.014 | 0.012 | 1.17× | no | | `one_se_rule` | 250x50 | 4.19 | 3.625 | 1.16× | no | | `pls_diagnostic_q` | 250x50 | 3.164 | 2.762 | 1.15× | yes | | `filter_y_outlier_mad` | 250x50 | 0.008 | 0.007 | 1.14× | yes | | `aom_pls` | 250x50 | 7.392 | 6.546 | 1.13× | no | | `di_pls` | 250x50 | 4.805 | 4.278 | 1.12× | no | | `random_frog_select` | 250x50 | 127.179 | 114.949 | 1.11× | no | | `rosa` | 250x50 | 2.901 | 2.612 | 1.11× | no | | `stability_select` | 250x50 | 899.269 | 810.255 | 1.11× | no | | `pcr` | 250x50 | 3.686 | 3.338 | 1.1× | no | | `pp_arpls` | 250x50 | 3.671 | 3.351 | 1.1× | no | | `pp_derivate` | 250x50 | 0.011 | 0.01 | 1.1× | yes | | `pp_range_disc` | 250x50 | 0.108 | 0.098 | 1.1× | yes | | `aug_linear_drift` | 250x50 | 0.012 | 0.011 | 1.09× | no | | `aug_spline_y_perturbations` | 250x50 | 0.869 | 0.798 | 1.09× | no | | `kernel_pls_rbf` | 250x50 | 5.298 | 4.849 | 1.09× | no | | `aug_detector_rolloff` | 250x50 | 0.113 | 0.105 | 1.08× | no | | `pp_from_absorbance` | 250x50 | 0.064 | 0.059 | 1.08× | no | | `sipls_select` | 250x50 | 5.119 | 4.723 | 1.08× | yes | | `aug_spike_noise` | 250x50 | 0.015 | 0.014 | 1.07× | yes | | `t2_select` | 250x50 | 2.995 | 2.808 | 1.07× | no | | `pls_diagnostic_t2` | 250x50 | 2.767 | 2.622 | 1.06× | no | | `pls_lda` | 250x50 | 2.874 | 2.713 | 1.06× | no | | `pp_osc` | 250x50 | 0.125 | 0.118 | 1.06× | no | | `randomization_select` | 250x50 | 248.644 | 234.457 | 1.06× | no | | `sparse_simpls` | 250x50 | 2.835 | 2.676 | 1.06× | no | | `wvc_select` | 250x50 | 2.707 | 2.556 | 1.06× | yes | | `irf_select` | 250x50 | 209.158 | 200.04 | 1.05× | no | | `pp_wavelet_pca` | 250x50 | 5.789 | 5.498 | 1.05× | no | | `emcuve_select` | 250x50 | 2319.37 | 2239.376 | 1.04× | no | | `mir_pls` | 250x50 | 2.877 | 2.779 | 1.04× | no | | `missing_aware_nipals` | 250x50 | 2.64 | 2.546 | 1.04× | yes | | `aug_rotate_translate` | 250x50 | 0.035 | 0.034 | 1.03× | no | | `fck` | 250x50 | 0.412 | 0.4 | 1.03× | yes | | `mb_pls` | 250x50 | 2.877 | 2.787 | 1.03× | yes | | `pp_detrend` | 250x50 | 0.061 | 0.059 | 1.03× | yes | | `pp_imodpoly` | 250x50 | 1.332 | 1.298 | 1.03× | no | | `pp_rnv` | 250x50 | 0.226 | 0.219 | 1.03× | no | | `variable_select_sr` | 250x50 | 460.034 | 445.445 | 1.03× | no | | `vip_spa_select` | 250x50 | 139.195 | 135.084 | 1.03× | no | | `bve_select` | 250x50 | 546.854 | 537.166 | 1.02× | no | | `channel_dropout` | 250x50 | 0.054 | 0.053 | 1.02× | yes | | `ecr` | 250x50 | 3.381 | 3.317 | 1.02× | no | | `robust_pls` | 250x50 | 2.819 | 2.752 | 1.02× | no | | `st_select` | 250x50 | 459.026 | 449.459 | 1.02× | no | | `aug_hetero_noise` | 250x50 | 0.133 | 0.132 | 1.01× | no | | `filter_x_outlier_lof` | 250x50 | 9.178 | 9.075 | 1.01× | no | | `interval_select` | 250x50 | 1252.074 | 1241.355 | 1.01× | no | | `pls_monitoring` | 250x50 | 2.65 | 2.613 | 1.01× | yes | | `pop_pls` | 250x50 | 7.656 | 7.601 | 1.01× | no | | `rep_select` | 250x50 | 786.827 | 776.422 | 1.01× | no | | `spa_select` | 250x50 | 586.863 | 583.073 | 1.01× | no | | `aug_batch_effect` | 50x250 | 0.007 | 0.007 | 1.0× | no | | `aug_dead_band` | 50x250 | 0.006 | 0.006 | 1.0× | yes | | `aug_edge_artifacts_combined` | 250x50 | 1.233 | 1.233 | 1.0× | yes | | `aug_multiplicative_noise` | 250x50 | 0.006 | 0.006 | 1.0× | no | | `aug_poly_drift` | 250x50 | 0.038 | 0.038 | 1.0× | yes | | `aug_random_x_operation` | 250x50 | 0.04 | 0.04 | 1.0× | no | | `aug_spline_smoothing` | 250x50 | 0.002 | 0.002 | 1.0× | no | | `filter_y_outlier_iqr` | 250x50 | 0.005 | 0.005 | 1.0× | no | | `filter_y_outlier_percentile` | 250x50 | 0.005 | 0.005 | 1.0× | no | | `filter_y_outlier_zscore` | 250x50 | 0.001 | 0.001 | 1.0× | no | | `lw_pls` | 250x50 | 28.055 | 28.18 | 1.0× | yes | | `magnitude_warp` | 250x50 | 0.054 | 0.054 | 1.0× | no | | `opls` | 250x50 | 2.721 | 2.727 | 1.0× | no | | `pls` | 250x50 | 2.519 | 2.531 | 1.0× | yes | | `pp_iasls` | 250x50 | 1.207 | 1.207 | 1.0× | no | | `pp_normalize` | 250x50 | 0.027 | 0.027 | 1.0× | yes | | `pp_resampler` | 250x50 | 0.032 | 0.032 | 1.0× | yes | | `pp_savgol` | 250x50 | 0.074 | 0.074 | 1.0× | no | | `pp_simple_scale` | 250x50 | 0.019 | 0.019 | 1.0× | no | | `pso_select` | 250x50 | 244.809 | 244.659 | 1.0× | no | | `split_systematic_circular` | 250x50 | 0.01 | 0.01 | 1.0× | no | | `weighted_pls` | 250x50 | 2.549 | 2.553 | 1.0× | no | | `approximate_press` | 250x50 | 63.856 | 64.282 | 0.99× | no | | `aug_temperature` | 50x250 | 2.257 | 2.281 | 0.99× | no | | `cars_select` | 250x50 | 881.249 | 890.493 | 0.99× | no | | `pp_airpls` | 250x50 | 1.054 | 1.061 | 0.99× | no | | `ridge_pls` | 250x50 | 2.588 | 2.602 | 0.99× | yes | | `scars_select` | 250x50 | 5.217 | 5.292 | 0.99× | no | | `shaving_select` | 250x50 | 484.502 | 489.939 | 0.99× | no | | `aug_stray_light` | 250x50 | 0.509 | 0.52 | 0.98× | no | | `group_sparse_pls` | 250x50 | 3.827 | 3.896 | 0.98× | no | | `ipw_select` | 250x50 | 418.938 | 425.922 | 0.98× | no | | `split_spxy_fold` | 250x50 | 1.5 | 1.529 | 0.98× | yes | | `wvc_threshold_select` | 250x50 | 403.396 | 411.566 | 0.98× | no | | `o2pls` | 250x50 | 2.996 | 3.101 | 0.97× | no | | `pp_flex_svd` | 250x50 | 0.5 | 0.518 | 0.97× | no | | `pp_gaussian` | 250x50 | 0.155 | 0.159 | 0.97× | no | | `pp_snip` | 250x50 | 0.937 | 0.963 | 0.97× | no | | `so_pls` | 250x50 | 3.523 | 3.623 | 0.97× | no | | `continuum_regression` | 250x50 | 3.536 | 3.671 | 0.96× | yes | | `ga_select` | 250x50 | 704.945 | 736.865 | 0.96× | no | | `iriv_select` | 250x50 | 1457.833 | 1512.358 | 0.96× | no | | `pp_beads` | 250x50 | 19.474 | 20.317 | 0.96× | no | | `pp_flex_pca` | 250x50 | 0.518 | 0.538 | 0.96× | yes | | `wavelength_stretch` | 250x50 | 0.093 | 0.097 | 0.96× | no | | `aug_particle_size` | 50x250 | 0.329 | 0.345 | 0.95× | yes | | `local_warp` | 250x50 | 0.144 | 0.152 | 0.95× | no | | `vissa_select` | 250x50 | 2275.394 | 2383.617 | 0.95× | yes | | `aom_preprocess` | 200x40 | 1.662 | 1.768 | 0.94× | no | | `aug_emsc_distort` | 50x250 | 0.015 | 0.016 | 0.94× | no | | `filter_x_outlier_isolation_forest` | 250x50 | 6.273 | 6.699 | 0.94× | no | | `pp_emsc` | 250x50 | 0.051 | 0.054 | 0.94× | no | | `cppls` | 250x50 | 2.477 | 2.672 | 0.93× | no | | `split_split_splitter` | 250x50 | 0.445 | 0.478 | 0.93× | no | | `filter_x_outlier_mahalanobis` | 250x50 | 0.802 | 0.893 | 0.9× | no | | `n_pls` | 250x50 | 26.142 | 28.899 | 0.9× | no | | `split_kennard_stone` | 250x50 | 0.991 | 1.101 | 0.9× | no | | `ds` | 250x50 | 3.281 | 3.686 | 0.89× | yes | | `aug_mixup` | 50x250 | 0.007 | 0.008 | 0.88× | yes | | `aug_truncated_peak` | 250x50 | 0.085 | 0.098 | 0.87× | yes | | `gauss_jitter` | 250x50 | 0.046 | 0.053 | 0.87× | no | | `pp_modpoly` | 250x50 | 4.813 | 5.544 | 0.87× | no | | `aug_moisture` | 50x250 | 0.569 | 0.659 | 0.86× | no | | `filter_x_outlier_robust_mahalanobis` | 250x50 | 2.356 | 2.739 | 0.86× | no | | `pls_glm` | 250x50 | 3.989 | 4.663 | 0.86× | no | | `pp_rolling_ball` | 250x50 | 0.282 | 0.327 | 0.86× | yes | | `pp_wavelet` | 250x50 | 0.006 | 0.007 | 0.86× | yes | | `split_kbins_stratified` | 250x50 | 0.006 | 0.007 | 0.86× | yes | | `filter_quality` | 250x50 | 0.029 | 0.034 | 0.85× | no | | `split_spxy` | 250x50 | 1.491 | 1.764 | 0.85× | no | | `uve_select` | 250x50 | 756.746 | 887.221 | 0.85× | no | | `split_kmeans` | 250x50 | 4.253 | 5.092 | 0.84× | no | | `aug_path_length` | 250x50 | 0.005 | 0.006 | 0.83× | yes | | `filter_x_outlier_pca_residual` | 250x50 | 0.539 | 0.649 | 0.83× | no | | `random_subspace_pls` | 250x50 | 13.879 | 17.196 | 0.81× | no | | `pds` | 250x50 | 3.097 | 3.886 | 0.8× | no | | `filter_x_outlier_pca_leverage` | 250x50 | 0.444 | 0.563 | 0.79× | yes | | `bagging_pls` | 250x50 | 16.589 | 21.333 | 0.78× | yes | | `variable_select_vip` | 250x50 | 6.344 | 8.242 | 0.77× | yes | | `pls_cox` | 250x50 | 3.844 | 5.12 | 0.75× | yes | | `pls_logistic` | 250x50 | 3.636 | 4.922 | 0.74× | yes | | `unsharp_mask` | 250x50 | 0.062 | 0.084 | 0.74× | yes | | `pp_haar` | 250x50 | 0.005 | 0.007 | 0.71× | no | | `pp_to_absorbance` | 250x50 | 0.062 | 0.088 | 0.7× | yes | | `band_perturb` | 250x50 | 0.019 | 0.029 | 0.66× | no | | `filter_leverage` | 250x50 | 1.572 | 2.394 | 0.66× | yes | | `pp_asls` | 250x50 | 0.58 | 0.885 | 0.66× | no | | `gpr_pls` | 250x50 | 6.567 | 10.253 | 0.64× | no | | `pp_baseline` | 250x50 | 0.009 | 0.014 | 0.64× | yes | | `split_spxy_g_fold` | 250x50 | 0.004 | 0.007 | 0.57× | yes | | `pp_frac_to_pct` | 250x50 | 0.002 | 0.004 | 0.5× | yes | | `pp_first_derivative` | 250x50 | 0.006 | 0.028 | 0.21× | yes | | `pp_kubelka_munk` | 250x50 | 0.005 | 0.027 | 0.19× | yes | ## Caveats - Proxy only: a real CUDA backend must beat host↔device transfer + launch latency, which the BLAS proxy doesn't capture. CUDA typically wins only well above the dashboard sizes (large n and/or p). - Methods in the `benefits` bucket that also `grow with size` are the highest-value CUDA targets (kernel/Gram-matrix PLS, GPR-PLS, multi-block, SVD/PCR, AOM selection). - Re-run after adding larger benchmark sizes or live `cuda-on` timings for a sharper verdict.