c++ 如何用valgrind做好代码分析?

beq87vna  于 2024-01-09  发布在  其他
关注(0)|答案(2)|浏览(170)

我已经开始使用valgrind,特别是用于代码分析的工具“callgrind”。
为了开始,我创建了一个用于数值积分的共享库(我实现了一个抽象类接口和一些专门用于求积公式的派生类,例如Simpson,Trapezoidal,Midpoint)。在这一点上,我在应用程序中使用test库,我想使用callgrind来检测主要瓶颈并优化代码。
因此,我在调试模式下编译了可执行文件,并使用Kcachegrind分析了程序的行为。
我在主程序下面附上了:实质上,我创建了一个基类“NUMERICAL_INTEGRATION”,它是每个求积公式的模板,然后我测试了一些函数。

  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <functional>
  4. #include "Quadrature.hpp"
  5. //#include <matplot/matplot.h>
  6. int main()
  7. {
  8. /*--- MODULE FOR NUMERICAL INTEGRATION --TESTING------- */
  9. using namespace Integrate_1D;
  10. NUMERICAL_INTEGRATION<MidPointQuadrature> nIntegrationMID;
  11. NUMERICAL_INTEGRATION<GaussLegeandreQuadrature> nIntegrationGL;
  12. NUMERICAL_INTEGRATION<SimpsonQuadrature> nIntegrationSIMPS;
  13. NUMERICAL_INTEGRATION<TrapzQuadrature> nIntegrationTRAPZ;
  14. // Example : Integration of f(x) = x:
  15. // All the formulas has to be exact for this function:
  16. auto ToIntegrate0 = [](double x)
  17. {
  18. return x;
  19. };
  20. double xSTART = 0.0;
  21. double xEND = 2.0;
  22. double EXACT_RES0 = 2.0;
  23. unsigned int N0;
  24. std::vector<double> degrees0;
  25. std::vector<std::vector<double>> errors0_(3,std::vector<double>(4));
  26. std::cout <<"********************************************\n";
  27. std::cout<< " TESTING FOR f(x) =x \n";
  28. std::cout<< "********************************************\n";
  29. N0=2;
  30. double MID_RES0 = nIntegrationMID(ToIntegrate0,xSTART,xEND,N0);
  31. double TRPZ_RES0 = nIntegrationTRAPZ(ToIntegrate0,xSTART,xEND,N0);
  32. double SIMPS_RES0 = nIntegrationSIMPS(ToIntegrate0,xSTART,xEND,N0);
  33. double GL_RES0 = nIntegrationGL(ToIntegrate0,xSTART,xEND,N0);
  34. std::cout << "********** TEST WITH N="<<N0<<"**************\n";
  35. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES0 <<"\n";
  36. std::cout << "Mid-point-result : " << MID_RES0 << "\n";
  37. std::cout << "Trapezoidal-result : " << TRPZ_RES0 << "\n";
  38. std::cout << "Simpson-result : " << SIMPS_RES0 << "\n";
  39. std::cout << "Gauss-Legendre-result : "<< GL_RES0 << "\n";
  40. errors0_[0][0] = abs(MID_RES0-EXACT_RES0);
  41. errors0_[0][1]= abs(TRPZ_RES0-EXACT_RES0);
  42. errors0_[0][2] = abs(SIMPS_RES0-EXACT_RES0);
  43. errors0_[0][3] = abs(GL_RES0-EXACT_RES0);
  44. std::cout << "***************************************\n";
  45. N0=4;
  46. MID_RES0 = nIntegrationMID(ToIntegrate0,xSTART,xEND,N0);
  47. TRPZ_RES0 = nIntegrationTRAPZ(ToIntegrate0,xSTART,xEND,N0);
  48. SIMPS_RES0 = nIntegrationSIMPS(ToIntegrate0,xSTART,xEND,N0);
  49. GL_RES0 = nIntegrationGL(ToIntegrate0,xSTART,xEND,N0);
  50. std::cout << "********** TEST WITH N="<<N0<<"**************\n";
  51. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES0 <<"\n";
  52. std::cout << "Mid-point-result : " << MID_RES0 << "\n";
  53. std::cout << "Trapezoidal-result : " << TRPZ_RES0 << "\n";
  54. std::cout << "Simpson-result : " << SIMPS_RES0 << "\n";
  55. std::cout << "Gauss-Legendre-result : "<< GL_RES0 << "\n";
  56. // Fill the error vector:
  57. errors0_[1][0] = abs(MID_RES0-EXACT_RES0);
  58. errors0_[1][1] = abs(TRPZ_RES0-EXACT_RES0);
  59. errors0_[1][2] = abs(SIMPS_RES0-EXACT_RES0);
  60. errors0_[1][3] = abs(GL_RES0-EXACT_RES0);
  61. std::cout << "***************************************\n";
  62. N0=8;
  63. MID_RES0 = nIntegrationMID(ToIntegrate0,xSTART,xEND,N0);
  64. TRPZ_RES0 = nIntegrationTRAPZ(ToIntegrate0,xSTART,xEND,N0);
  65. SIMPS_RES0 = nIntegrationSIMPS(ToIntegrate0,xSTART,xEND,N0);
  66. GL_RES0 = nIntegrationGL(ToIntegrate0,xSTART,xEND,N0);
  67. std::cout << "********** TEST WITH N="<<N0<<"**************\n";
  68. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES0 <<"\n";
  69. std::cout << "Mid-point-result : " << MID_RES0 << "\n";
  70. std::cout << "Trapezoidal-result : " << TRPZ_RES0 << "\n";
  71. std::cout << "Simpson-result : " << SIMPS_RES0 << "\n";
  72. std::cout << "Gauss-Legendre-result : "<< GL_RES0 << "\n";
  73. std::cout << "ERROR FOR N=8 : f(x)=x" <<std::endl;
  74. std::cout << "trapz: " << TRPZ_RES0-EXACT_RES0<<std::endl;
  75. std::cout << "midpoint: " << MID_RES0-EXACT_RES0<<std::endl;
  76. std::cout << "simpson: " << SIMPS_RES0-EXACT_RES0<<std::endl;
  77. std::cout << "GaussLegendre: " << GL_RES0-EXACT_RES0<<std::endl;
  78. std::cout << "******************************************\n";
  79. std::cout << "******************************************\n";
  80. std::cout << "*******END TEST FOR f(x) = x *********\n\n\n\n";
  81. // Example : Integration of f(x) = sin(x):
  82. auto ToIntegrate = [](double x)
  83. {
  84. return sin(x);
  85. };
  86. xSTART = 0.0;
  87. xEND = M_PI;
  88. unsigned int N;
  89. std::vector<double> degrees;
  90. std::vector<std::vector<double>> errors_(4,std::vector<double>(4));
  91. std::vector<double> currErrors(4);
  92. double EXACT_RES = 2.0;
  93. std::cout <<"********************************************\n";
  94. std::cout<< " TESTING FOR f(x) = sin(x) \n";
  95. std::cout<< "********************************************\n";
  96. N=2;
  97. degrees.push_back(double(N));
  98. double MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
  99. double TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
  100. double SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
  101. double GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
  102. std::cout << "********** TEST WITH N="<<N<<"**************\n";
  103. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
  104. std::cout << "Mid-point-result : " << MID_RES << "\n";
  105. std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
  106. std::cout << "Simpson-result : " << SIMPS_RES << "\n";
  107. std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";
  108. errors_[0][0] = abs(MID_RES-EXACT_RES);
  109. errors_[0][1]= abs(TRPZ_RES-EXACT_RES);
  110. errors_[0][2] = abs(SIMPS_RES-EXACT_RES);
  111. errors_[0][3] = abs(GL_RES-EXACT_RES);
  112. std::cout << "***************************************\n";
  113. N=4;
  114. degrees.push_back(double(N));
  115. MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
  116. TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
  117. SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
  118. GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
  119. std::cout << "********** TEST WITH N="<<N<<"**************\n";
  120. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
  121. std::cout << "Mid-point-result : " << MID_RES << "\n";
  122. std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
  123. std::cout << "Simpson-result : " << SIMPS_RES << "\n";
  124. std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";
  125. // Fill the error vector:
  126. errors_[1][0] = abs(MID_RES-EXACT_RES);
  127. errors_[1][1] = abs(TRPZ_RES-EXACT_RES);
  128. errors_[1][2] = abs(SIMPS_RES-EXACT_RES);
  129. errors_[1][3] = abs(GL_RES-EXACT_RES);
  130. std::cout << "***************************************\n";
  131. N=5;
  132. degrees.push_back(double(N));
  133. MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
  134. TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
  135. SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
  136. GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
  137. std::cout << "********** TEST WITH N="<<N<<"**************\n";
  138. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
  139. std::cout << "Mid-point-result : " << MID_RES << "\n";
  140. std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
  141. std::cout << "Simpson-result : " << SIMPS_RES << "\n";
  142. std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";
  143. // Fill the error vector:
  144. errors_[2][0] = abs(MID_RES-EXACT_RES);
  145. errors_[2][1] = abs(TRPZ_RES-EXACT_RES);
  146. errors_[2][2] = abs(SIMPS_RES-EXACT_RES);
  147. errors_[2][3] = abs(GL_RES-EXACT_RES);
  148. std::cout << "***************************************\n";
  149. N=8;
  150. degrees.push_back(double(N));
  151. MID_RES = nIntegrationMID(ToIntegrate,xSTART,xEND,N);
  152. TRPZ_RES = nIntegrationTRAPZ(ToIntegrate,xSTART,xEND,N);
  153. SIMPS_RES = nIntegrationSIMPS(ToIntegrate,xSTART,xEND,N);
  154. GL_RES = nIntegrationGL(ToIntegrate,xSTART,xEND,N);
  155. std::cout << "********** TEST WITH N="<<N<<"**************\n";
  156. std::cout << "EXACT-RESULT of the integration: "<<EXACT_RES <<"\n";
  157. std::cout << "Mid-point-result : " << MID_RES << "\n";
  158. std::cout << "Trapezoidal-result : " << TRPZ_RES << "\n";
  159. std::cout << "Simpson-result : " << SIMPS_RES << "\n";
  160. std::cout << "Gauss-Legendre-result : "<< GL_RES << "\n";
  161. // Fill the error vector:
  162. errors_[3][0] = abs(MID_RES-EXACT_RES);
  163. errors_[3][1] = abs(TRPZ_RES-EXACT_RES);
  164. errors_[3][2] = abs(SIMPS_RES-EXACT_RES);
  165. errors_[3][3] = abs(GL_RES-EXACT_RES);
  166. std::cout << "***************************************\n";
  167. std::vector<double> mid_error = {errors_[0][0],errors_[1][0],errors_[2][0],errors_[3][0]};
  168. std::vector<double> trz_error = {errors_[0][1],errors_[1][1],errors_[2][1],errors_[3][1]};
  169. std::vector<double> simps_error = {errors_[0][2],errors_[1][2],errors_[2][2],errors_[3][2]};
  170. std::vector<double> gl_error = {errors_[0][3],errors_[1][3],errors_[2][3],errors_[3][3]};

字符串
现在,问题是,当我尝试使用valgrind。
附件中你可以找到一个屏幕截图,显示了该程序(kcachegrind)的主要用途。
首先,我不明白什么是_dl_start,为什么它需要相对总成本的82%。有人能给予我一些解释吗?
第二个问题是:代码分析和优化代码的最佳实践是什么?特别是,有一些指导方针可以检测主要瓶颈并使代码更快?
抱歉,如果我太笼统,但我是新来的,我不知道的东西在具体的。
谢谢大家的回答。
valgrind: kcachegrind

qyzbxkaa

qyzbxkaa1#

_dl_start是“动态库”代码,用于加载共享库并执行符号的运行时链接。如果你在这些例程上花费了超过80%的时间,那么你的测试程序肯定只是在做一些微不足道的事情。你需要做一个更大的测试,这样callgrind就有更多的东西要测量。
或者,你需要使用客户端请求机制。你可以使用这个机制,callgrind不会检测任何东西,直到你告诉它,这将是你想要分析的函数。如果你有一个小的测试用例,这将允许你从谷壳中挑选小麦。

hwamh0ep

hwamh0ep2#

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.分析调用:

Valgrind的callgrind工具可以用于代码分析,以识别热点和测量函数调用频率。
valgrind --tool=callgrind ./your_program
这将生成一个callgrind.out文件。
kcachegrind callgrind. out. *
kcachegrind callgrind. out. *

温馨提示:

**抑制文件:**您可能会在第三方库中遇到误报或不相关的问题。请创建抑制文件以从Valgrind输出中排除特定问题。
**Valgrind选项:**Valgrind提供各种自定义选项。根据您的需求查看文档以获取其他选项。
**迭代过程:**一次解决一个问题,重新运行Valgrind以确保您取得进展。

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

展开查看全部

相关问题