@@ -598,30 +598,43 @@ static int run_decompress(CliSettings s) {
598598 size_t output_size = 0 ;
599599
600600 try {
601+ std::vector<uint8_t > orig;
602+ if (!s.original_path .empty ()) {
603+ orig = read_binary_file (s.original_path );
604+ }
605+
601606 const auto t0 = std::chrono::high_resolution_clock::now ();
602607 Pipeline::decompressFromFile (s.input_path , &d_output, &output_size, 0 );
603608 FZ_CUDA_CHECK (cudaDeviceSynchronize ());
604609 const auto t1 = std::chrono::high_resolution_clock::now ();
605610 double host_ms = std::chrono::duration<double , std::milli>(t1 - t0).count ();
606611
607- std::vector<uint8_t > host (output_size);
608- if (output_size > 0 ) {
609- FZ_CUDA_CHECK (cudaMemcpy (host.data (), d_output, output_size, cudaMemcpyDeviceToHost));
612+ // Truncate to the original size if we have it (to remove chunk padding)
613+ size_t usable_size = output_size;
614+ if (!orig.empty () && orig.size () < output_size) {
615+ usable_size = orig.size ();
616+ }
617+
618+ std::vector<uint8_t > host (usable_size);
619+ if (usable_size > 0 ) {
620+ FZ_CUDA_CHECK (cudaMemcpy (host.data (), d_output, usable_size, cudaMemcpyDeviceToHost));
610621 }
611622
612623 if (!s.output_path .empty ()) {
613624 write_binary_file (s.output_path , host.data (), host.size ());
614625 }
615626
616627 if (s.report || !s.original_path .empty ()) {
617- double tput = static_cast <double >(output_size ) / (host_ms * 1e-3 ) / 1e9 ;
628+ double tput = static_cast <double >(usable_size ) / (host_ms * 1e-3 ) / 1e9 ;
618629 std::cout << " \n [Decompress Report]\n "
619- << " Output size: " << output_size << " bytes\n "
620- << " Time: " << std::fixed << std::setprecision (3 ) << host_ms << " ms\n "
630+ << " Output size: " << usable_size << " bytes\n " ;
631+ if (usable_size != output_size) {
632+ std::cout << " (Padded size: " << output_size << " bytes, truncated to match original)\n " ;
633+ }
634+ std::cout << " Time: " << std::fixed << std::setprecision (3 ) << host_ms << " ms\n "
621635 << " Throughput: " << std::setprecision (2 ) << tput << " GB/s\n " ;
622636
623- if (!s.original_path .empty ()) {
624- std::vector<uint8_t > orig = read_binary_file (s.original_path );
637+ if (!orig.empty ()) {
625638 if (orig.size () != host.size ()) {
626639 std::cout << " Compare error: Size mismatch! Original=" << orig.size ()
627640 << " , Reconstructed=" << host.size () << " \n " ;
@@ -683,6 +696,7 @@ static int run_benchmark(CliSettings s) {
683696 FZ_CUDA_CHECK (cudaDeviceSynchronize ());
684697
685698 TimingSummary compress_stats, decompress_stats;
699+ std::vector<uint8_t > final_recon;
686700
687701 for (int i = 0 ; i < s.benchmark_runs ; ++i) {
688702 const auto t0 = std::chrono::high_resolution_clock::now ();
@@ -704,6 +718,11 @@ static int run_benchmark(CliSettings s) {
704718 }
705719 decompress_stats.add (std::chrono::duration<double , std::milli>(t3 - t2).count (), pipeline->getLastPerfResult ().dag_elapsed_ms );
706720
721+ if ((s.report || !s.original_path .empty ()) && i == s.benchmark_runs - 1 ) {
722+ final_recon.resize (recon_size);
723+ FZ_CUDA_CHECK (cudaMemcpy (final_recon.data (), d_recon, recon_size, cudaMemcpyDeviceToHost));
724+ }
725+
707726 if (!pipeline->isPoolManagedDecompOutput () && d_recon) {
708727 FZ_CUDA_CHECK (cudaFree (d_recon));
709728 }
@@ -712,6 +731,37 @@ static int run_benchmark(CliSettings s) {
712731 print_summary (" compress" , compress_stats, payload_bytes);
713732 print_summary (" decompress" , decompress_stats, payload_bytes);
714733
734+ if (s.report || !s.original_path .empty ()) {
735+ double ratio = static_cast <double >(payload_bytes) / compressed_size;
736+ std::cout << " \n [Quality Report]\n "
737+ << " Input size: " << payload_bytes << " bytes\n "
738+ << " Compressed size: " << compressed_size << " bytes\n "
739+ << " Ratio: " << std::fixed << std::setprecision (2 ) << ratio << " x\n " ;
740+
741+ std::vector<uint8_t > orig;
742+ if (!s.original_path .empty ()) {
743+ orig = read_binary_file (s.original_path );
744+ } else {
745+ orig = input_bytes;
746+ }
747+
748+ if (!orig.empty () && orig.size () == final_recon.size ()) {
749+ Metrics m;
750+ if (s.type == " f32" ) m = calc_metrics<float >(orig, final_recon);
751+ else if (s.type == " f64" ) m = calc_metrics<double >(orig, final_recon);
752+ else if (s.type == " i32" ) m = calc_metrics<int32_t >(orig, final_recon);
753+ else if (s.type == " i64" ) m = calc_metrics<int64_t >(orig, final_recon);
754+
755+ std::cout << " Value Range: [" << std::scientific << m.val_min << " , " << m.val_max << " ] (Span: " << m.val_range << " )\n "
756+ << " Max Abs Error: " << std::scientific << m.max_err << " \n "
757+ << " PSNR: " << std::fixed << std::setprecision (2 ) << m.psnr << " dB\n "
758+ << " NRMSE: " << std::scientific << m.nrmse << " \n " ;
759+ } else if (!orig.empty ()) {
760+ std::cout << " Compare error: Size mismatch! Original=" << orig.size ()
761+ << " , Reconstructed=" << final_recon.size () << " \n " ;
762+ }
763+ }
764+
715765 } catch (...) {
716766 if (d_input) FZ_CUDA_CHECK_WARN (cudaFree (d_input));
717767 throw ;
0 commit comments