私はc ++でヒープに割り当てられているメモリの量をよりよく理解しようとしています。基本的に、いくつかの2Dベクトルを埋める以外に何もしない小さなテストプログラムを作成しました。私はこれをLinux 64ビットVMで実行しており、メモリのプロファイルを作成するためにvalgrindのMassifツールを使用しています。
このテストを実行している環境:Win10のVirtualBoxで実行されているLinux VM。VM構成:ベースメモリ:5248MB、4CPU、上限100%、ディスクタイプVDI(動的に割り当てられたストレージ)。
c ++メモリプロファイリングテストプログラム:
/**
* g++ -std=c++11 test.cpp -o test.o
*/
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main(int argc, char **arg) {
int n = stoi(arg[1]);
vector<vector<int> > matrix1(n);
vector<vector<int> > matrix2(n);
vector<vector<int> > matrix3(n);
vector<vector<int> > matrix4(n);
vector<vector<int> > matrix5(n);
vector<vector<int> > matrix6(n);
vector<vector<int> > matrix7(n);
vector<vector<int> > matrix8(n);
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix1[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix2[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix3[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix4[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix5[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix6[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix7[i].push_back(j);
}
}
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
matrix8[i].push_back(j);
}
}
}
の異なる値でメモリプロファイルを抽出するために次のbashスクリプトを実行しますn
(test.oは上記のプログラムで、g ++ -std = c ++ 11でコンパイルされています。g++はバージョン5.3.0です)
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 250
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 500
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 1000
valgrind --tool=massif --massif-out-file=massif-n2000.txt ./test.o 2000
valgrind --tool=massif --massif-out-file=massif-n4000.txt ./test.o 4000
valgrind --tool=massif --massif-out-file=massif-n8000.txt ./test.o 8000
valgrind --tool=massif --massif-out-file=massif-n16000.txt ./test.o 16000
valgrind --tool=massif --massif-out-file=massif-n32000.txt ./test.o 32000
これにより、次の結果が得られます。
|--------------------------------|
| n | peak heap memory usage |
|-------|------------------------|
| 250 | 2.1 MiB |
| 500 | 7.9 MiB |
| 1000 | 31.2 MiB |
| 2000 | 124.8 MiB |
| 4000 | 496.5 MiB |
| 8000 | 1.9 GiB |
| 16000 | 6.2 GiB |
| 32000 | 6.1 GiB |
|--------------------------------|
各行列のサイズはn ^ 2になります。合計8つの行列があるため、メモリ使用量はと予想されましたf(n) = 8 * n^2
。
質問1 n = 250からn = 8000まで、n * = 2でメモリ使用量が4倍になるのはなぜですか?
n = 16000からn = 32000までは、valgrindが実際にメモリの減少を報告するため、非常に奇妙なことが起こっています。
質問2 n = 16000とn = 32000の間で何が起こっていますか。理論的にはより多くのデータを割り当てる必要があるのに、ヒープメモリが少なくなる可能性はありますか
以下のn = 16000およびn = 32000のmassif-visualizer出力を参照してください。
1)行列ベクトルのサイズ(およびそのメモリフットプリント)がn 2として増加するため、nを2倍にすると、メモリ使用量が4倍になります。(漸近的なものとは対照的に)正確な関係からの逸脱は、さまざまな要因によるものです(たとえばmalloc / std::allocator
、によって使用されるメタデータ、によって使用されるブロックサイズ倍加方法vector
)
2)メモリが不足し始めているため、Linuxがページングを開始しています。(アクティブ+ページングされた)合計メモリ使用量--pages-as-heap=yes
を確認する場合に使用します。(出典:http : //valgrind.org/docs/manual/ms-manual.html)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加