26901 ^ 2 * sizeof(double)のCのmallocがあります
これは私にここで最大の価値が何であるかを考えさせましたか?
また、この2D配列にアクセスするためのマクロの定義に問題がありますか?
#define DN(i,j) ((int)i * ny + (int)j)
これは私にとってうまくいっていないようです-または少なくとも私はそれが確かではありません。 A [DN(indx、jndx)]が実際に何を見ているのかを伝えるために、マクロでtotalviewを実行する方法を理解できません。
Glibcが使用するような典型的なアロケータを想定すると、いくつかの観察があります:
malloc
に対するそれらの領域の可用性に依存します。malloc
から mmap
への呼び出しなど)の影響を受けます。これが 簡単なプログラム であり、可能な最大のブロックを割り当てます(gcc largest_malloc_size.c -Wall -O2
でコンパイルします:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void *malloc_wrap(size_t size)
{
void *p = malloc(size);
if (p) {
printf("Allocated %zu bytes from %p to %p\n", size, p, p + size);
}
else {
printf("Failed to allocated %zu bytes\n", size);
}
return p;
}
int main()
{
size_t step = 0x1000000;
size_t size = step;
size_t best = 0;
while (step > 0)
{
void *p = malloc_wrap(size);
if (p) {
free(p);
best = size;
}
else {
step /= 0x10;
}
size += step;
}
void *p = malloc_wrap(best);
if (p) {
pause();
return 0;
}
else {
return 1;
}
}
上記のプログラム(./a.out
)をLinux stanley 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux
マシンで実行すると、次の結果が得られます。
<snip>
Allocated 2919235584 bytes from 0x9763008 to 0xb7763008
Allocated 2936012800 bytes from 0x8763008 to 0xb7763008
Failed to allocated 2952790016 bytes
Failed to allocated 2953838592 bytes
Failed to allocated 2953904128 bytes
Failed to allocated 2953908224 bytes
Allocated 2936012800 bytes from 0x85ff008 to 0xb75ff008
これは正確に2800MiBの割り当てです。 /proc/[number]/maps
から関連するマッピングを確認します。
<snip>
0804a000-0804b000 rw-p 00001000 08:07 3413394 /home/matt/anacrolix/public/stackoverflow/a.out
085ff000-b7600000 rw-p 00000000 00:00 0 [heap]
b7600000-b7621000 rw-p 00000000 00:00 0
b7621000-b7700000 ---p 00000000 00:00 0
b7764000-b7765000 rw-p 00000000 00:00 0
b7765000-b78b8000 r-xp 00000000 08:08 916041 /lib/tls/i686/cmov/libc-2.11.1.so
<snip>
bfc07000-bfc1c000 rw-p 00000000 00:00 0 [stack]
プログラムデータとコードの間の領域、および ユーザー/カーネルメモリ空間の境界 (明らかにこのシステムでは3G/1G)にぴったり合う共有ライブラリマッピングの領域でヒープが拡張されているようです。
この結果は、mallocを使用して割り当て可能な最大スペースがおおよそ次の値に等しいことを示唆しています。
GlibcとLinuxの実装に関しては、次の手動スニペットが非常に重要です。
Normally, malloc() allocates memory from the heap, and adjusts the size
of the heap as required, using sbrk(2). When allocating blocks of mem‐
ory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation
allocates the memory as a private anonymous mapping using mmap(2).
MMAP_THRESHOLD is 128 kB by default, but is adjustable using mal‐
lopt(3).
MAP_ANONYMOUS
The mapping is not backed by any file; its contents are initial‐
ized to zero.
このテストはx86カーネルで行われました。非常に大きなメモリ領域が返されますが、x86_64カーネルからも同様の結果が期待されます。他のオペレーティングシステムでは、マッピングの配置や大きなmalloc
sの処理が異なるため、結果がかなり異なる場合があります。
それはあなたのmalloc実装に依存します!
Wikipediaによると、「v2.3リリース以降、GNU Cライブラリ(glibc)は、それ自体がdlmalloc v2.7.0に基づく変更されたptmalloc2を使用します。」dlmallocは、Doug Leaのmallocを指します。この実装で注意すべき重要な点は、大きなmallocはオペレーティングシステムのメモリマップファイル機能によって実現されるため、これらのブロックは、隣接するブロックを見つけるという多くの問題がなくても非常に大きくなる可能性があります。
Mallocの質問に回答します(指定しないOSに依存します)。
_#define DN(i,j) ((int)i * ny + (int)j)
_
誰かがDN(a+b,c)
を実行する可能性があるため、安全ではありません
_((int)a+b * ny + (int)c)
_
これはおそらくあなたが望んでいたものではありません。そこにたくさんの括弧を入れてください:
_#define DN(i,j) ((int)(i) * ny + (int)(j))
_
DN(indx,jndx)
が何を指しているかを確認するには、printf("%d\n",DN(indx,jndx));
できる最大のメモリブロックaskmalloc()
は、最大のsize_t
値です。これは、SIZE_MAX
からの<limits.h>
です。あなたができる最大の量成功リクエストは明らかにオペレーティングシステムと個々のマシンの設定に依存しています。
マクロは安全ではありません。これは、int
変数を使用してインデックス計算を実行します。これは、最大32767の範囲である必要があります。これより大きい値を指定すると、符号付きオーバーフローが発生し、動作が未定義になる可能性があります。その型は有効な配列インデックスを保持できる必要があるため、size_t
として計算を行うのが最善の方法です。
#define DN(i, j) ((size_t)(i) * ny + (size_t)(j))
(ただし、i
またはj
に負の値を指定すると、範囲外のインデックスが取得されます)。
Mallocへの呼び出しのサイズパラメータは、サイズの種類で、実装によって異なります。詳細は この質問 を参照してください。
これは私にここで最大の価値が何であるかを考えさせましたか?
26'901 ^ 2 = 723'663'801。 doubleが8バイトの場合、8GB未満です。私はメモリの多くを割り当てることにまったく問題がないことを確認し、私のアプリは(64ビットシステムで)日常的にはるかに多く割り当てます。 (私が今まで見た中で最大のメモリ消費量は420GB(640GB RAMを搭載したSolaris 10 numaシステム上)で、最大24GBの連続ブロックがありました。)
最大値はプラットフォームに依存するため、特定が困難です。32ビットシステムと同様に、ユーザー空間/カーネル空間の分割に依存します。現状では、実際の物理的な限界に最初に到達すると思いますRAM-libcが割り当てることができる限界に到達する前に(そしてカーネルは気にしません、十分なRAMそれを固定するためにあるかどうか)さえ考慮せずに仮想メモリを拡張するだけです。