我已经开始使用 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 是一个强大的工具,用于检测 C 和 C++ 程序中的内存泄漏、内存损坏以及其他与内存相关的问题。要使用 Valgrind 执行良好的代码分析,请按照下列步骤操作:
确保您的系统上安装了 Valgrind。您可以使用特定于您的操作系统的包管理器来安装它。例如,在基于 Debian 的系统上:
sudo apt-get install valgrind
确保您的代码使用调试符号(-g 标志)进行编译,以便从 Valgrind 获得更准确、信息更丰富的结果。
gcc -g -o your_program your_source_code.c
使用 Valgrind 运行您的程序以检测内存泄漏。 Valgrind 的 memcheck 工具通常用于此目的。
valgrind --leak-check=full ./your_program
--leak-check=full:提供有关内存泄漏的详细信息。 检查 Valgrind 输出是否有任何报告的内存泄漏。它将提供有关内存分配位置和丢失位置的信息。
Valgrind 的 memcheck 工具还有助于检测内存损坏和其他与内存相关的错误。
valgrind --tool=memcheck --track-origins=yes ./your_program
--tool=memcheck:使用 memcheck 工具。 --track-origins=yes:尝试显示未初始化值的来源。 检查 Valgrind 输出是否有任何报告的错误,并在代码中解决它们。
Valgrind 的 callgrind 工具可用于代码分析,以识别热点并测量函数调用频率。
valgrind --tool=callgrind ./your_program
这将生成一个 callgrind.out 文件。使用 kcachegrind 可视化分析信息。
kcachegrind 调用grind.out。*
kcachegrind 调用grind.out。*
抑制文件:您可能会在第三方库中遇到误报或不相关的问题。创建抑制文件以从 Valgrind 输出中排除特定问题。
Valgrind 选项: Valgrind 提供各种定制选项。根据您的需要查看文档以获取其他选项。
迭代过程:一次修复一个问题并重新运行 Valgrind 以确保取得进展。
通过执行以下步骤,您可以有效地使用 Valgrind 来分析您的 C 或 C++ 代码、识别内存相关问题并提高软件的整体质量。