数组的大小是否受到int上限(2147483647)的限制?
我正在做一些 Project Euler 练习,并且遇到了一个场景,我有 想要大于 2,147,483,647(C# 中 int
的上限)的数组。
当然,这些是大型数组,但例如,我不能这样做
// fails
bool[] BigArray = new BigArray[2147483648];
// also fails, cannot convert uint to int
ArrayList BigArrayList = new ArrayList(2147483648);
那么,我可以有更大的数组吗?
编辑: 这是一个阿特金筛,你知道,所以我只想要一个非常大的: D
I'm doing some Project Euler exercises and I've run into a scenario where I have want arrays which are larger than 2,147,483,647 (the upper limit of int
in C#).
Sure these are large arrays, but for instance, I can't do this
// fails
bool[] BigArray = new BigArray[2147483648];
// also fails, cannot convert uint to int
ArrayList BigArrayList = new ArrayList(2147483648);
So, can I have bigger arrays?
EDIT:
It was for a Sieve of Atkin, you know, so I just wanted a really big one :D
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
每当您使用这么大的数组时,您可能应该尝试找到更好的问题解决方案。 但话虽这么说,我仍然会尝试回答你的问题。
正如这篇文章中提到的,有一个 2 .Net 中任何对象的 GB 限制。 适用于所有 x86、x64 和 IA64。
另外,如果您在堆栈上定义的数组太大,则会出现堆栈溢出。 如果您在堆上定义数组,它将尝试将其全部分配在一个大的连续块中。 最好使用在堆上隐式动态分配的 ArrayList。 这不会让你超过 2GB,但可能会让你更接近它。
我认为只有当您使用 x64 或 IA64 架构和操作系统时,堆栈大小限制才会更大。 使用 x64 或 IA64,您将拥有 64 位可分配内存,而不是 32 位。
如果您无法一次分配全部数组列表,您可以分部分分配它。
使用数组列表并在具有 6GB RAM 的 x64 Windows 2008 计算机上一次添加 1 个对象,我最多可以获得 ArrayList 的大小:134217728。所以我真的认为你必须找到一个更好的解决方案来解决你的问题不使用尽可能多的内存。 也许写入文件而不是使用 RAM。
Anytime you are working with an array this big, you should probably try to find a better solution to the problem. But that being said I'll still attempt to answer your question.
As mentioned in this article there is a 2 GB limit on any object in .Net. For all x86, x64 and IA64.
Also if you define an array too big on the stack, you will have a stack overflow. If you define the array on the heap, it will try to allocate it all in one big continuous block. It would be better to use an ArrayList which has implicit dynamic allocation on the heap. This will not allow you to get past the 2GB, but will probably allow you to get closer to it.
I think the stack size limit will be bigger only if you are using an x64 or IA64 architecture and operating system. Using x64 or IA64 you will have 64-bit allocatable memory instead of 32-bit.
If you are not able to allocate the array list all at once, you can probably allocate it in parts.
Using an array list and adding 1 object at a time on an x64 Windows 2008 machine with 6GB of RAM, the most I can get the ArrayList to is size: 134217728. So I really think you have to find a better solution to your problem that does not use as much memory. Perhaps writing to a file instead of using RAM.
据我所知,即使在 64 位上,数组限制也固定为 int32。 单个对象的最大大小有上限。 然而,你可以很容易地得到一个漂亮的大锯齿状数组。
更差; 因为 x64 中的引用更大,所以对于 ref 类型数组,您实际上在单个数组中获得更少元素。
请参阅此处:
应该注意的是,在 .NET 4.5 中,内存大小限制可以通过 gcAllowVeryLargeObjects 标志,但是,这不会更改最大维度大小。 关键点是,如果您有自定义类型的数组或多维数组,那么您现在的内存大小可以超过 2GB。
The array limit is, afaik, fixed as int32 even on 64-bit. There is a cap on the maximum size of a single object. However, you could have a nice big jagged array quite easily.
Worse; because references are larger in x64, for ref-type arrays you actually get less elements in a single array.
See here:
It should be noted that in .NET 4.5 the memory size limit is optionally removed by the gcAllowVeryLargeObjects flag, however, this doesn't change the maximum dimension size. The key point is that if you have arrays of a custom type, or multi-dimension arrays, then you can now go beyond 2GB in memory size.
您根本不需要那么大的数组。
当你的方法遇到资源问题时,不要只看如何扩展资源,还要看方法。 :)
这是一个使用 3 MB 缓冲区来使用埃拉托斯特尼筛法计算素数的类。 该类会跟踪您计算素数的程度,并且当需要扩展范围时,它会创建一个缓冲区来测试另外 300 万个数字。
它将找到的素数保存在列表中,当范围扩大时,以前的素数将用于排除缓冲区中的数字。
我做了一些测试,大约 3 MB 的缓冲区是最有效的。
You don't need an array that large at all.
When your method runs into resource problems, don't just look at how to expand the resources, look at the method also. :)
Here's a class that uses a 3 MB buffer to calculate primes using the sieve of Eratosthenes. The class keeps track of how far you have calculated primes, and when the range needs to be expanded it creates a buffer to test another 3 million numbers.
It keeps the found prime numbers in a list, and when the range is expanded the previos primes are used to rule out numbers in the buffer.
I did some testing, and a buffer around 3 MB is most efficient.
我相信即使在 64 位 CLR 中,每个对象也有 2GB(或者可能是 1GB - 我记不清了)的限制。 这将阻止您创建更大的数组。 Array.CreateInstance 仅采用 Int32 大小参数这一事实也很具有启发性。
从更广泛的角度来看,我怀疑如果您需要那么大的数组,您确实应该改变解决问题的方式。
I believe that even within a 64 bit CLR, there's a limit of 2GB (or possibly 1GB - I can't remember exactly) per object. That would prevent you from creating a larger array. The fact that Array.CreateInstance only takes Int32 arguments for sizes is suggestive too.
On a broader note, I suspect that if you need arrays that large you should really change how you're approaching the problem.
我是 C# 的新手(即这周学习),所以我不确定 ArrayList 是如何实现的确切细节。 但是,我猜想,由于您尚未为 ArrayList 示例定义类型,因此该数组将被分配为对象引用数组。 这很可能意味着您实际上根据架构分配 4-8Gb 内存。
I'm very much a newbie with C# (i.e. learning it this week), so I'm not sure of the exact details of how ArrayList is implemented. However, I would guess that as you haven't defined a type for the ArrayList example, then the array would be allocated as an array of object references. This might well mean that you are actually allocating 4-8Gb of memory depending on the architecture.
根据 MSDN,字节数组的索引不能大于大于 2147483591。对于 4.5 之前的 .NET,它也是数组的内存限制。 在 .NET 4.5 中,这个最大值是相同的,但对于其他类型,它可以达到 2146435071。
这是用于说明的代码:
According to MSDN, the index for array of bytes cannot be greater than 2147483591. For .NET prior to 4.5 it also was a memory limit for an array. In .NET 4.5 this maximum is the same, but for other types it can be up to 2146435071.
This is the code for illustration: