Google CPU Profilerを使用してC/C++マルチスレッドプログラムの性能分析を行う
GoogleのgperftoolsキットにはCPU Profiler(以下pprofと略す)が含まれており、C/C++マルチスレッドプログラムの性能分析をオリジナルでサポートしています.GNU Profilerがマルチスレッド性能プロファイルをオリジナルでサポートできないよりも、pprofの方が実用的です.
依存条件
gperftools:https://googledrive.com/host/0B6NtGsLhIcf7MWxMMF9JdTN3UVk/gperftools-2.2.tar.gz
cmake:http://www.cmake.org/download/
The KDE Software Development Kit(kdesdk):このrpmパッケージを含むkcachegrindツールが含まれています.
サンプルコード
完全な項目は以下の通りです.https://github.com/lostaway/Woody-Ye-s-Code-Share/tree/master/CpuProfilerExample
依存条件
gperftools:https://googledrive.com/host/0B6NtGsLhIcf7MWxMMF9JdTN3UVk/gperftools-2.2.tar.gz
cmake:http://www.cmake.org/download/
The KDE Software Development Kit(kdesdk):このrpmパッケージを含むkcachegrindツールが含まれています.
サンプルコード
完全な項目は以下の通りです.https://github.com/lostaway/Woody-Ye-s-Code-Share/tree/master/CpuProfilerExample
// main.cpp
#include
#include
void *FastFunc(void *_arg)
{
double sum = 0;
for(int i = 0; i < 100000000; i++)
{
sum += 1;
}
return (NULL);
}
void *SlowFunc(void *_arg)
{
double sum = 0;
for(int i = 0; i < 100000000; i++)
{
sum *= 3;
sum /= 3;
sum += 1;
}
return (NULL);
}
void *AllFunc(void *_arg)
{
FastFunc(NULL);
SlowFunc(NULL);
return (NULL);
}
int main(int argc, char *argv[])
{
pthread_t tidFast = 0, tidSlow = 0, tidAll = 0;
pthread_create(&tidFast, NULL, FastFunc, NULL);
pthread_create(&tidSlow, NULL, SlowFunc, NULL);
pthread_create(&tidAll, NULL, AllFunc, NULL);
pthread_join(tidFast, NULL);
pthread_join(tidSlow, NULL);
pthread_join(tidAll, NULL);
return (0);
}
# CMake compile script
PROJECT(CpuProfilerExample)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# usage "cmake -DUSE_CPU_PROFILER=ON .." or "cmake -DUSE_CPU_PROFILER=OFF .."
MESSAGE(STATUS USE_CPU_PROFILER=${USE_CPU_PROFILER})
SET(SRC main.cpp)
INCLUDE_DIRECTORIES()
LINK_DIRECTORIES($ENV{GPERFTOOLS_ROOT}/lib)
ADD_EXECUTABLE(CpuProfilerExample ${SRC})
TARGET_LINK_LIBRARIES(CpuProfilerExample pthread)
IF(USE_CPU_PROFILER)
TARGET_LINK_LIBRARIES(CpuProfilerExample profiler)
ENDIF()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#!/bin/sh
echo "start CpuProfilerExample CPU profile"
env CPUPROFILE=CpuProfilerExample.prof ./CpuProfilerExample
exit 1
#!/bin/sh
echo "Display CpuProfilerExample CPU profile in Kcachegrind"
pprof --callgrind CpuProfilerExample CpuProfilerExample.prof > CpuProfilerExample.callgrind
nohup kcachegrind CpuProfilerExample.callgrind > /dev/null &
exit 1
操作步骤
pprof可以在不修改源码的情况下,通过在编译时链接profiler库,程序启动前设置特定的环境变量来开启CPU剖析功能。进入CpuProfilerExample项目根目录:
$ mkdir build $ cmake -DUSE_CPU_PROFILER=ON .. $ gmake $ cd ../bin $ ./startCpuProfile.sh
プログラムの実行が完了すると、binディレクトリの下に「CpuProfilerExample.prof」プロファイルが生成されます.実行:$ ./displayProfileInKcachegrind.sh
KCAcheGrindプログラムを起動し、性能分析結果を表示する:
呼び出し図では、各矩形ボックスは関数を表し、上部は関数名であり、下部はその関数とその呼び出しの関数がプログラムの総実行時間に占める割合を表す.パーセンテージのみを見ると,浮動小数点数乗算加算を実行したSlowFunc関数は,総実行時間の85.39%を占め,実際のコードと一致した.総稼働時間の14.61%を占める浮動小数点数加算FastFunc関数を実行した.
剖析結果には「タイムスライス」の概念もある.左側の関数のリストを参照してくださいstart_threadのCalledフィールド「527」はstart_を表すthread関数が呼び出す関数は527個のタイムスライスを消費した.各呼び出しの関数が消費するタイムスライスの数を、呼び出し図の矢印に示す.したがって、SlowFunc関数は、占有率および占有タイムスライスの観点から例示的なプログラムのパフォーマンスボトルネックである.
まとめ
プログラム性能の最適化は、もともと遅い仕事で、pprofがあってプログラムの性能のボトルネックに迅速に位置決めすることができて、的確に最適化します.pprofの基本的な使い方を熟知した後、さらに学習する目標は、作業中の複雑なプログラムのパフォーマンスボトルネック、サードパーティライブラリのパフォーマンスボトルネック、システム呼び出しのパフォーマンスボトルネックを分析することです.
リファレンス
[1] Google CPU Profiler Manuals,http://gperftools.googlecode.com/svn/trunk/doc/cpuprofile.html