如何使用 valgrind 进行良好的代码分析?

问题描述 投票:0回答:1

我已经开始使用 valgrind,特别是用于代码分析的工具“callgrind”。

首先,我创建了一个用于数值积分的共享库(我实现了一个抽象类接口和一些专门求积公式的派生类,例如辛普森、梯形、中点)。 此时,我在应用程序中使用测试库,我想使用 callgrind 来检测主要瓶颈并优化代码。

因此,我已经在调试模式下编译了可执行文件,并且正在使用 Kcachegrind 分析程序的行为。

我在下面附上了主程序: 实质上,我创建了一个基类“NUMERICAL_INTEGRATION”,它针对每个求积公式进行了模板化,然后我测试了一些函数。

#include <stdio.h>
#include <iostream>
#include <functional>

#include "Quadrature.hpp"
//#include <matplot/matplot.h>




int main()
{



   /*--- MODULE FOR NUMERICAL INTEGRATION --TESTING------- */
   using namespace Integrate_1D;
   NUMERICAL_INTEGRATION<MidPointQuadrature> nIntegrationMID;
   NUMERICAL_INTEGRATION<GaussLegeandreQuadrature> nIntegrationGL;
   NUMERICAL_INTEGRATION<SimpsonQuadrature> nIntegrationSIMPS;
   NUMERICAL_INTEGRATION<TrapzQuadrature> nIntegrationTRAPZ;


   // Example : Integration of f(x) = x:

   // All the formulas has to be exact for this function:
   auto ToIntegrate0 = [](double x)
   {
     return x;
   };

   double xSTART = 0.0;
   double xEND   = 2.0;
   double EXACT_RES0 = 2.0;
   unsigned int N0;
   std::vector<double> degrees0;
   std::vector<std::vector<double>> errors0_(3,std::vector<double>(4));


   std::cout <<"********************************************\n";
   std::cout<< "  TESTING FOR f(x) =x                       \n";
   std::cout<< "********************************************\n";

   N0=2;
   double MID_RES0 = nIntegrationMID(ToIntegrate0,xSTART,xEND,N0);
   double TRPZ_RES0 = nIntegrationTRAPZ(ToIntegrate0,xSTART,xEND,N0);
   double SIMPS_RES0 = nIntegrationSIMPS(ToIntegrate0,xSTART,xEND,N0);
   double GL_RES0 = nIntegrationGL(ToIntegrate0,xSTART,xEND,N0);
   
   std::cout << "********** TEST WITH N="<<N0<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES0 <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES0 << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES0 << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES0 << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES0 << "\n";

   errors0_[0][0] = abs(MID_RES0-EXACT_RES0);
   errors0_[0][1]= abs(TRPZ_RES0-EXACT_RES0);
   errors0_[0][2] = abs(SIMPS_RES0-EXACT_RES0);
   errors0_[0][3] = abs(GL_RES0-EXACT_RES0);

   std::cout << "***************************************\n";

   N0=4;
   MID_RES0 = nIntegrationMID(ToIntegrate0,xSTART,xEND,N0);
   TRPZ_RES0 = nIntegrationTRAPZ(ToIntegrate0,xSTART,xEND,N0);
   SIMPS_RES0 = nIntegrationSIMPS(ToIntegrate0,xSTART,xEND,N0);
   GL_RES0 = nIntegrationGL(ToIntegrate0,xSTART,xEND,N0);
   
   std::cout << "********** TEST WITH N="<<N0<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES0 <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES0 << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES0 << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES0 << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES0 << "\n";

   // Fill the error vector:
   errors0_[1][0] = abs(MID_RES0-EXACT_RES0);
   errors0_[1][1] = abs(TRPZ_RES0-EXACT_RES0);
   errors0_[1][2] = abs(SIMPS_RES0-EXACT_RES0);
   errors0_[1][3] = abs(GL_RES0-EXACT_RES0);
   std::cout << "***************************************\n";

   N0=8;
   MID_RES0 = nIntegrationMID(ToIntegrate0,xSTART,xEND,N0);
   TRPZ_RES0 = nIntegrationTRAPZ(ToIntegrate0,xSTART,xEND,N0);
   SIMPS_RES0 = nIntegrationSIMPS(ToIntegrate0,xSTART,xEND,N0);
   GL_RES0 = nIntegrationGL(ToIntegrate0,xSTART,xEND,N0);
   
   std::cout << "********** TEST WITH N="<<N0<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES0 <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES0 << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES0 << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES0 << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES0 << "\n";

   std::cout << "ERROR FOR N=8 : f(x)=x" <<std::endl;
   std::cout << "trapz: " << TRPZ_RES0-EXACT_RES0<<std::endl;
   std::cout << "midpoint: " << MID_RES0-EXACT_RES0<<std::endl;
   std::cout << "simpson: " << SIMPS_RES0-EXACT_RES0<<std::endl;
   std::cout << "GaussLegendre: " << GL_RES0-EXACT_RES0<<std::endl;
   std::cout << "******************************************\n";
   std::cout << "******************************************\n";
   std::cout << "*******END TEST FOR f(x) = x *********\n\n\n\n";
   
   // Example : Integration of f(x) = sin(x):
   auto ToIntegrate = [](double x)
   {
     return sin(x);
   };
  
   xSTART = 0.0;
   xEND   = M_PI;
   unsigned int N;
   std::vector<double> degrees;
   std::vector<std::vector<double>> errors_(4,std::vector<double>(4));
   std::vector<double> currErrors(4);
   
   double EXACT_RES = 2.0;
   std::cout <<"********************************************\n";
   std::cout<< "  TESTING FOR f(x) = sin(x)                 \n";
   std::cout<< "********************************************\n";

   N=2;
   degrees.push_back(double(N));
   double MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
   double TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
   double SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
   double GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
   std::cout << "********** TEST WITH N="<<N<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";

   errors_[0][0] = abs(MID_RES-EXACT_RES);
   errors_[0][1]= abs(TRPZ_RES-EXACT_RES);
   errors_[0][2] = abs(SIMPS_RES-EXACT_RES);
   errors_[0][3] = abs(GL_RES-EXACT_RES);
   std::cout << "***************************************\n";
   
   N=4;
   degrees.push_back(double(N));
   MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
   TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
   SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
   GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N); 
   std::cout << "********** TEST WITH N="<<N<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";

   // Fill the error vector:
   errors_[1][0] = abs(MID_RES-EXACT_RES);
   errors_[1][1] = abs(TRPZ_RES-EXACT_RES);
   errors_[1][2] = abs(SIMPS_RES-EXACT_RES);
   errors_[1][3] = abs(GL_RES-EXACT_RES);
   std::cout << "***************************************\n";
   
   N=5;
   degrees.push_back(double(N));
 
   MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
   TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
   SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
   GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
  
  
   std::cout << "********** TEST WITH N="<<N<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";
   
   // Fill the error vector:
   errors_[2][0] = abs(MID_RES-EXACT_RES);
   errors_[2][1] = abs(TRPZ_RES-EXACT_RES);
   errors_[2][2] = abs(SIMPS_RES-EXACT_RES);
   errors_[2][3] = abs(GL_RES-EXACT_RES);
   std::cout << "***************************************\n";
   N=8;
   degrees.push_back(double(N));
 
   MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
   TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
   SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
   GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
  
  
   std::cout << "********** TEST WITH N="<<N<<"**************\n";
   std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
   std::cout << "Mid-point-result : "   <<   MID_RES << "\n";
   std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
   std::cout << "Simpson-result : " <<     SIMPS_RES << "\n";
   std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";
   
   // Fill the error vector:
   errors_[3][0] = abs(MID_RES-EXACT_RES);
   errors_[3][1] = abs(TRPZ_RES-EXACT_RES);
   errors_[3][2] = abs(SIMPS_RES-EXACT_RES);
   errors_[3][3] = abs(GL_RES-EXACT_RES);
   std::cout << "***************************************\n";
   
   std::vector<double> mid_error = {errors_[0][0],errors_[1][0],errors_[2][0],errors_[3][0]};
   std::vector<double> trz_error = {errors_[0][1],errors_[1][1],errors_[2][1],errors_[3][1]};
   std::vector<double> simps_error = {errors_[0][2],errors_[1][2],errors_[2][2],errors_[3][2]};
   std::vector<double> gl_error = {errors_[0][3],errors_[1][3],errors_[2][3],errors_[3][3]};

现在,问题是当我尝试使用 valgrind 时。

随附的截图显示了该程序(kcachegrind)的主要用法。

首先,我不明白什么是 _dl_start 以及为什么它占总相对成本的 82%。有人可以给我一些解释吗?

第二个问题是:代码分析和优化代码的最佳实践是什么?特别是,有指导方针来检测主要瓶颈并使您的代码更快吗?

如果我太笼统,请道歉,但我是新人,我不知道具体的事情。

谢谢大家的回答。

valgrind: kcachegrind

c++ coding-style valgrind scientific-computing
1个回答
0
投票

Valgrind 是一个强大的工具,用于检测 C 和 C++ 程序中的内存泄漏、内存损坏以及其他与内存相关的问题。要使用 Valgrind 执行良好的代码分析,请按照下列步骤操作:

1.安装 Valgrind:

确保您的系统上安装了 Valgrind。您可以使用特定于您的操作系统的包管理器来安装它。例如,在基于 Debian 的系统上:

sudo apt-get install valgrind

2.使用调试符号编译您的代码:

确保您的代码使用调试符号(-g 标志)进行编译,以便从 Valgrind 获得更准确、信息更丰富的结果。

gcc -g -o your_program your_source_code.c

3.内存泄漏检测:

使用 Valgrind 运行您的程序以检测内存泄漏。 Valgrind 的 memcheck 工具通常用于此目的。

valgrind --leak-check=full ./your_program

--leak-check=full:提供有关内存泄漏的详细信息。 检查 Valgrind 输出是否有任何报告的内存泄漏。它将提供有关内存分配位置和丢失位置的信息。

4.地址和内存错误:

Valgrind 的 memcheck 工具还有助于检测内存损坏和其他与内存相关的错误。

valgrind --tool=memcheck --track-origins=yes ./your_program

--tool=memcheck:使用 memcheck 工具。 --track-origins=yes:尝试显示未初始化值的来源。 检查 Valgrind 输出是否有任何报告的错误,并在代码中解决它们。

5. Callgrind 用于分析:

Valgrind 的 callgrind 工具可用于代码分析,以识别热点并测量函数调用频率。

valgrind --tool=callgrind ./your_program

这将生成一个 callgrind.out 文件。使用 kcachegrind 可视化分析信息。

kcachegrind 调用grind.out。*

kcachegrind 调用grind.out。*

温馨提示:

抑制文件:您可能会在第三方库中遇到误报或不相关的问题。创建抑制文件以从 Valgrind 输出中排除特定问题。

Valgrind 选项: Valgrind 提供各种定制选项。根据您的需要查看文档以获取其他选项。

迭代过程:一次修复一个问题并重新运行 Valgrind 以确保取得进展。

通过执行以下步骤,您可以有效地使用 Valgrind 来分析您的 C 或 C++ 代码、识别内存相关问题并提高软件的整体质量。

© www.soinside.com 2019 - 2024. All rights reserved.