Che*_*rek 6 c# pointers unsafe multidimensional-array
我需要在C#WinForms中声明方形矩阵,连续超过20000个项目.我读到了32位的2GB .Net对象大小限制以及64位操作系统中的相同情况.所以我理解单一答案 - 使用不安全的代码或使用C++编译器构建的独立库.
对我来说问题是值得的,因为ushort [20000,20000]小于2GB但实际上我甚至无法分配700MB的内存.我的限制是650MB,我不明白为什么 - 我有32位WinXP和3GB内存.我尝试使用Marshal.AllocHGlobal(700 << 20)但它抛出OutOfMemoryException,GC.GetTotalMemory在尝试分配内存之前返回4.5MB.
我发现只有很多人说使用不安全的代码,但我找不到如何在堆中声明2-dim数组的示例(任何堆栈都不能保存如此大量的数据)以及如何使用指针处理它.它是不安全的{}括号内的纯C++代码吗?
PS.请不要问为什么我需要如此庞大的数组...但如果你想 - 我需要分析文本(例如书籍)并找到很多索引.所以答案是 - 词之间关系的矩阵
编辑:有人可以提供一个使用不安全代码中的指针处理矩阵的小例子.我知道在32位以下不可能分配更多的空间,但我花了很多时间在谷歌搜索这样的例子,发现没什么
为什么要求巨大的二维阵列?您可以使用例如锯齿状阵列来模拟这种情况ushort[][]- 几乎同样快,并且您不会达到相同的单一对象限制.你当然还需要buckets-o-RAM,所以暗示x64 ......
ushort[][] arr = new ushort[size][];
for(int i = 0 ; i < size ; i++) {
arr[i] = new ushort[size];
}
Run Code Online (Sandbox Code Playgroud)
除此之外 - 您可能想要查看稀疏数组,eta向量和所有爵士乐.
我太高兴了!:) 最近我解决了这个问题 - 尝试使用数据库来解决它,但发现这种方法还远远不够完美。矩阵[20000,20000]被实现为单个表。即使正确设置了索引,在我的 PC 上创建超过 4 亿条记录所需的时间也大约是 1 小时。这对我来说并不重要。然后我运行算法来处理该矩阵(需要两次才能加入同一个表!),在它工作了半个多小时后,它甚至没有执行任何一步。之后我明白,唯一的方法是找到一种仅在内存中使用此类矩阵并再次返回 C# 的方法。
我创建了试点应用程序来测试内存分配过程,并使用不同的结构确定分配过程到底在哪里停止。
正如我在第一篇文章中所说,在 32 位 WinXP 下使用 2-dim 数组只能分配大约650MB 的空间。使用Win7和64位编译后的结果也很糟糕——不到700MB。
我使用 JAGGED ARRAYS [][] 而不是单个 2-dim 数组 [,],结果如下:
在发布模式下编译为 32 位应用程序 - WinXP 32 位 3GB phys。内存。- 1.45GB 在发布模式下编译为 64 位应用程序 - Win7 64 位 VM 下 2GB - 7.5GB
--我用于测试的应用程序来源附在这篇文章中。我在这里找不到如何附加源文件,因此只需描述设计部分并在此处放置手动代码。创建 WinForms 应用程序。将此类控件的默认名称放在表单上:1 个按钮、1 个数字向上和 1 个列表框在 .cs 文件中添加下一个代码并运行。
private void button1_Click(object sender, EventArgs e)
{
//Log(string.Format("Memory used before collection: {0}", GC.GetTotalMemory(false)));
GC.Collect();
//Log(string.Format("Memory used after collection: {0}", GC.GetTotalMemory(true)));
listBox1.Items.Clear();
if (string.IsNullOrEmpty(numericUpDown1.Text )) {
Log("Enter integer value");
}else{
int val = (int) numericUpDown1.Value;
Log(TryAllocate(val));
}
}
/// <summary>
/// Memory Test method
/// </summary>
/// <param name="rowLen">in MB</param>
private IEnumerable<string> TryAllocate(int rowLen) {
var r = new List<string>();
r.Add ( string.Format("Allocating using jagged array with overall size (MB) = {0}", ((long)rowLen*rowLen*Marshal.SizeOf(typeof(int))) >> 20) );
try {
var ar = new int[rowLen][];
for (int i = 0; i < ar.Length; i++) {
try {
ar[i] = new int[rowLen];
}
catch (Exception e) {
r.Add ( string.Format("Unable to allocate memory on step {0}. Allocated {1} MB", i
, ((long)rowLen*i*Marshal.SizeOf(typeof(int))) >> 20 ));
break;
}
}
r.Add("Memory was successfully allocated");
}
catch (Exception e) {
r.Add(e.Message + e.StackTrace);
}
return r;
}
#region Logging
private void Log(string s) {
listBox1.Items.Add(s);
}
private void Log(IEnumerable<string> s)
{
if (s != null) {
foreach (var ss in s) {
listBox1.Items.Add ( ss );
}
}
}
#endregion
Run Code Online (Sandbox Code Playgroud)
问题已经为我解决了。伙计们,先谢谢你们了!