web-dev-qa-db-ja.com

使用可能なメモリC ++ / g ++を取得する方法は?

使用可能なメモリに応じてバッファを割り当てたい。このように、処理を行うとメモリ使用量が増加しますが、使用可能なメモリ制限のままです。使用可能なメモリを取得する方法はありますか(仮想メモリまたは物理メモリの状態が変化するかどうかわかりません)。メソッドは、Windows、OS X、Linux、AIXで使用されるため、プラットフォームに依存しない必要があります。 (そして可能であれば、アプリケーションに使用可能なメモリの一部を割り当てたいと思います。実行中に変更されない誰かです)。

編集:構成可能なメモリ割り当てでそれをやった。ほとんどのOSがメモリを管理するため、これは良いアイデアではないことを理解していますが、私のアプリケーションはETLフレームワークでした(サーバーでの使用を意図していましたが、デスクトップでAdobe indesignのプラグインとしても使用されていました)。だから、スワップを使用する代わりに、ウィンドウが悪いallocを返し、他のアプリケーションが失敗し始めるため、私は問題に直面していました。そして、クラッシュを避けるように教えられたように、ただ優雅に分解しようとしていました。

61
theCakeCoder

これらの回答を読んだ後、私は非常に多くの人がOPのコンピューターメモリが他のものに属するというスタンスをとっていることに驚いています。 his computerとhisは、彼が適切だと考えるメモリです。たとえそれが主張している他のシステムを壊したとしてもです。興味深い質問です。より原始的なシステムでは、これを教えてくれるmemavail()がありました。 OPが他のシステムを混乱させることなく、必要なだけのメモリを消費すべきではないのはなぜですか?

これは、使用できるメモリの半分未満を割り当てるための、丁寧なソリューションです。出力は:

必須FFFFFFFF

必須7FFFFFFF

必須3FFFFFFF

割り当てられたメモリサイズ= 1FFFFFFF

#include <stdio.h>
#include <stdlib.h>

#define MINREQ      0xFFF   // arbitrary minimum

int main(void)
{
    unsigned int required = (unsigned int)-1; // adapt to native uint
    char *mem = NULL; 
    while (mem == NULL) {
        printf ("Required %X\n", required);
        mem = malloc (required);
        if ((required >>= 1) < MINREQ) {
            if (mem) free (mem);
            printf ("Cannot allocate enough memory\n");
            return (1);
        }
    }

    free (mem);
    mem = malloc (required);
    if (mem == NULL) {
        printf ("Cannot enough allocate memory\n");
        return (1);
    }
    printf ("Memory size allocated = %X\n", required);
    free (mem);
    return 0;
}
13
Weather Vane

UNIXライクなオペレーティングシステムでは、 sysconf があります。

#include <unistd.h>

unsigned long long getTotalSystemMemory()
{
    long pages = sysconf(_SC_PHYS_PAGES);
    long page_size = sysconf(_SC_PAGE_SIZE);
    return pages * page_size;
}

Windowsでは、 GlobalMemoryStatusEx があります。

#include <windows.h>

unsigned long long getTotalSystemMemory()
{
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx(&status);
    return status.ullTotalPhys;
}

ちょっとした空想#ifdefsとあなたは行ってもいいでしょう。

140
Travis Gockel

科学ソフトウェアのためにHPCでこれを実行したい理由があります。 (ゲーム、ウェブ、ビジネス、組み込みソフトウェアではありません)。科学ソフトウェアは、テラバイト単位のデータを定期的に通過して、1回の計算(または実行)(および数時間または数週間実行)を実行します-すべてをメモリに保存することはできませんまたはタブレットや電話では、科学ソフトウェアがペタバイト以上を処理することが期待されます。また、メモリの量によって、意味のあるメソッド/アルゴリズムの種類が決まります。ユーザーは常に記憶と方法を決定したいとは限らない-彼/彼女は心配する他のことを持っています。そのため、プログラマーは、使用可能なもの(最近は4Gbまたは8Gbまたは64Gbまたはその周辺)をよく理解して、メソッドが自動的に機能するか、より面倒なメソッドを選択するかを判断する必要があります。ディスクが使用されますが、メモリが望ましいです。そして、そのようなソフトウェアのユーザーは、そのようなソフトウェアを実行するときにコンピューター上であまりにも多くのことを行うことは推奨されません。実際、多くの場合、専用のマシン/サーバーを使用します。

29
Paresh M

これを行うためのプラットフォームに依存しない方法はありません。異なるオペレーティングシステムは異なるメモリ管理戦略を使用します。

これらの他のスタックオーバーフローの質問は役立ちます。

ただし、注意する必要があります。Linuxで使用可能なメモリの「実際の」値を取得するのは難しいことで有名です。プロセスによって使用されるオペレーティングシステムの表示は、プロセスに実際に割り当てられるものを保証するものではありません。

これは、ルーターなどの組み込みLinuxシステムを開発する際の一般的な問題であり、ハードウェアが許す限りバッファリングする必要があります。 Linux(C)でこの情報を取得する方法を示す例へのリンクは次のとおりです。

11
mikelong

Sysctl(man 3 sysctl)を使用したMac OS Xの例:

#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int main(void)
{
    int mib[2] = { CTL_HW, HW_MEMSIZE };
    u_int namelen = sizeof(mib) / sizeof(mib[0]);
    uint64_t size;
    size_t len = sizeof(size);

    if (sysctl(mib, namelen, &size, &len, NULL, 0) < 0)
    {
        perror("sysctl");
    }
    else
    {
        printf("HW.HW_MEMSIZE = %llu bytes\n", size);
    }
    return 0;
}

(他のBSDライクなオペレーティングシステムでも動作しますか?)

5
Paul R

以下のコードは、合計および空きメモリをメガバイト単位で示します。 FreeBSDで動作しますが、プラットフォーム上で同じ/類似のsysctlチューナブルを使用して、同じことを実行できるはずです(LinuxおよびOS Xには少なくともsysctlがあります)

#include <stdio.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>

int main(){
    int rc;
    u_int page_size;
    struct vmtotal vmt;
    size_t vmt_size, uint_size; 

    vmt_size = sizeof(vmt);
    uint_size = sizeof(page_size);

    rc = sysctlbyname("vm.vmtotal", &vmt, &vmt_size, NULL, 0);
    if (rc < 0){
       perror("sysctlbyname");
       return 1;
    }

    rc = sysctlbyname("vm.stats.vm.v_page_size", &page_size, &uint_size, NULL, 0);
    if (rc < 0){
       perror("sysctlbyname");
       return 1;
    }

    printf("Free memory       : %ld\n", vmt.t_free * (u_int64_t)page_size);
    printf("Available memory  : %ld\n", vmt.t_avm * (u_int64_t)page_size);

    return 0;
}

以下は、システムの vmstat(8) 出力と比較したプログラムの出力です。

~/code/memstats % cc memstats.c 
~/code/memstats % ./a.out 
Free memory       : 5481914368
Available memory  : 8473378816
~/code/memstats % vmstat 
 procs      memory      page                    disks     faults         cpu
 r b w     avm    fre   flt  re  pi  po    fr  sr ad0 ad1   in   sy   cs us sy id
 0 0 0   8093M  5228M   287   0   1   0   304 133   0   0  112 9597 1652  2  1 97
3
fnisi

これの「公式」機能  std::get_temporary_buffer()でした。ただし、プラットフォームに適切な実装があるかどうかをテストすることもできます。すべてのプラットフォームが期待どおりに動作するとは限りません。

3
MSalters

推測しようとする代わりに、ユーザーがバッファに使用するメモリの量を構成できるようにし、ある程度保守的なデフォルトを仮定することを検討しましたか?この方法では、オーバーライドなしで実行できます(わずかに遅くなる可能性があります)が、ユーザーがアプリで使用可能なXメモリがあることを知っている場合、その量を構成することでパフォーマンスを向上させることができます。

1
Mark B