Is there a reason to limit arrays to 32 bit only addressable ones?
Working around it might severely impact some HPC apps that manipulate large sets of data.
I understand that .NetCore might run on some platforms that are not 64 bits and not many applications need such large arrays. But this seems a very limiting decision as we see more and more platforms going 64 bits and we are coming into the age of massive data.
Working around it might severely impact some HPC apps that manipulate large sets of data.
What makes you say so? How severe would the impact actually be?
Arrays are a pretty fundamental part of .Net, so I think that supporting 64-bit arrays would not be trivial and would require a convincing argument.
Also, it was recently considered whether Span<T> should support 64-bit, but it was eventually decided it should not (at least for now).
You make sense. Without data there is no real discussion.
So I implemented a small test, the code is bellow. I am not sure how relevant the data is as I use a coarse real world time as proxy for execution time. At least it gets the ball rolling.
It has an impact of about 5% the first run but then the impact is drastically reduced in the next runs to around 0.3%. I guess the incremental compiler must optimize it after analyzing the first run. This is a cost I can live with. I was afraid it would be much more expensive as I have experienced in other virtual machines.
So my thoughts are:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace LargeArrayTest {
public class Program {
public static void Main(string[] args) {
long testLenght = int.MaxValue / 5;
int nbRuns = 20;
double accumulator = 0;
for (int i = 0; i < nbRuns; i++)
accumulator += testRun(testLenght);
Console.WriteLine("avg cost:" + (accumulator / nbRuns));
Console.WriteLine("Press Key To Close");
Console.ReadKey();
}
public static double testRun(long testLenght) {
long start = DateTime.Now.Ticks;
testLargeArray(testLenght);
double span1 = DateTime.Now.Ticks - start;
start = DateTime.Now.Ticks;
testLargeArray(testLenght);
double span2 = DateTime.Now.Ticks - start;
Console.Write("Array time :" + span1);
Console.Write(" Synthetic time:" + span2);
double diff = ((span2 - span1) * 100 / span1);
Console.WriteLine(" cost:" + diff + "%");
return diff;
}
public static void testLargeArray(long size) {
int[] data = new int[size];
for (int i = 0; i < size; i++)
data[i] = i;
long avg = 0;
for (int i = 0; i < data.Length; i++)
avg += data[i];
if (avg != (((size - 1) * size / 2)))
throw new Exception("wrong value");
}
public static void testLargeSyntheticArray(long size) {
SyntheticLargeArray<int> data = new SyntheticLargeArray<int>(size);
for (int i = 0; i < size; i++)
data[i] = i;
long avg = 0;
for (int i = 0; i < data.Length; i++)
avg += data[i];
if (avg != (((size - 1) * size / 2)))
throw new Exception("wrong value");
}
}
public class SyntheticLargeArray<T> {
T[][] data;
public long Length;
//const int MaxArraySize = int.MaxValue;
const int MaxArraySize = int.MaxValue / 256;
public SyntheticLargeArray(long length) {
int nbSegments = (int)length / MaxArraySize;
int last = (int)length % MaxArraySize;
this.Length = length;
if (last == 0) {
data = new T[nbSegments][];
for (int i = 0; i < nbSegments; i++)
data[i] = new T[MaxArraySize];
} else {
data = new T[nbSegments + 1][];
for (int i = 0; i < nbSegments; i++)
data[i] = new T[MaxArraySize];
data[nbSegments + 1] = new T[last];
}
}
public T this[long index] {
get {
int up = (int)(index >> 32);
int low = (int)(index & 0xffffffff);
return data[up][low];
}
set {
int up = (int)(index >> 32);
int low = (int)(index & 0xffffffff);
data[up][low] = value;
}
}
}
}
@svdh2 it sounds like there is nothing we need to do here. Please reactivate if that is not the case.
Can we reopen this ticket please?
We are writing HPC applications and the 2G elements limitation of arrays is increasingly becoming a problem.
It means we cannot allocate a contiguous array for holding our data. Instead we have to either do cumbersome splitting of the data, or allocate native memory and use unsafe pointers, with all the problems and incompatibilities it raises (e.g. cannot use MKL matrix operations on non-contiguous data, cannot use System.Numerics.Vector on native memory, etc).
I could understand the decision not to support it a decade ago, but now it's becoming untenable. It forces us to write thousands of lines of special (and often inefficient) code to work around it. We have compute farm nodes with 1TB of RAM each, yet we can only allocate 8GB of continuous floats using .NET Core. Heck, we have graphic cards with more memory than that.
How much more RAM, how many more years until Microsoft .NET Core people agree this situation is silly?
.NET Core has made some incredible improvements toward HPC friendliness (e.g. Span
I also think that Span not supporting 64-bits indices was a huge letdown. It would have at least helped with native memory allocations and given you a stepping stone towards full 64-bits support in .NET.
Most helpful comment
Can we reopen this ticket please?
We are writing HPC applications and the 2G elements limitation of arrays is increasingly becoming a problem.
It means we cannot allocate a contiguous array for holding our data. Instead we have to either do cumbersome splitting of the data, or allocate native memory and use unsafe pointers, with all the problems and incompatibilities it raises (e.g. cannot use MKL matrix operations on non-contiguous data, cannot use System.Numerics.Vector on native memory, etc).
I could understand the decision not to support it a decade ago, but now it's becoming untenable. It forces us to write thousands of lines of special (and often inefficient) code to work around it. We have compute farm nodes with 1TB of RAM each, yet we can only allocate 8GB of continuous floats using .NET Core. Heck, we have graphic cards with more memory than that.
How much more RAM, how many more years until Microsoft .NET Core people agree this situation is silly?
.NET Core has made some incredible improvements toward HPC friendliness (e.g. Span and unmanaged generic constraint). Let's take advantage of this momentum. Removing the 32-bits array limitation would go a long way.