EDIT
Stavo riflettendo su un'attuazione più completamente descritto della mia risposta, ho pensato di accodamento. Non sono sicuro che la parallelizzazione possa essere d'aiuto, forse dipende dallo initializer
.
using System;
using System.Linq;
public static T[][][] NewJagged<T>(
int h,
int w,
ing d,
Func<int, int, int, T> initializer = null,
bool parallelize = true)
{
if (h < 1)
{
throw new ArgumentOutOfRangeException("h", h, "Dimension less than 1.")
}
if (w < 1)
{
throw new ArgumentOutOfRangeException("w", w, "Dimension less than 1.")
}
if (d < 1)
{
throw new ArgumentOutOfRangeException("d", d, "Dimension less than 1.")
}
if (initializer == null)
{
initializer = (i, j, k) => default(T);
}
if (parallelize)
{
return NewJaggedParalellImpl(h, w, d, initializer);
}
return NewJaggedImpl(h, w, d, initializer);
}
private static T[][][] NewJaggedImpl<T>(
int h,
int w,
int d,
Func<int, int, int, T> initializer)
{
var result = new T[h][][];
for (var i = 0; i < h; i++)
{
result[i] = new T[w][];
for (var j = 0; j < w; j++)
{
result[i][j] = new T[d];
for (var k = 0; k < d; k++)
{
result[i][j][k] = initializer(i, j, k);
}
}
}
return result;
}
private static T[][][] NewJaggedParalellImpl<T>(
int h,
int w,
int d,
Func<int, int, int, T> initializer)
{
var result = new T[h][][];
ParallelEnumerable.Range(0, h).ForAll(i =>
{
result[i] = new T[w][];
ParallelEnumerable.Range(0, w).ForAll(j =>
{
result[i][j] = new T[d];
ParallelEnumerable.Range(0, d).ForAll(k =>
{
result[i][j][k] = initializer(i, j, k);
});
});
});
return result;
}
Questo rende la funzione del tutto generico, ma ancora si lascia la sintassi semplice,
var foo1 = NewJagged<Foo>(1000, 1000, 500);
Si potrebbe comunque ottenere l'immaginazione e popolare in paralell su inizializzazione,
var foo2 = NewJagged<Foo>(
1000,
1000,
5000,
(i, j, k) =>
{
var pos = (i * 1000 * 500) + (j * 500) + k;
return ((pos % 2) == 0) ? new Foo() : null;
});
in questo caso , popolando con un effetto a scacchiera (credo);
Questo può non sembrare inizialmente per rispondere il vostro problema ...
Se si ha una funzione, qualcosa di simile
public static T[][][] ThreeDimmer<T>(int h, int w, int d) where T : new()
{
var result = new T[h][][];
for (var i = 0; i < h; i++)
{
result[i] = new T[w][];
for (var j = 0; j < w; j++)
{
result[i][j] = new T[d];
for (var k = 0; k < d; k++)
{
result[i][j][k] = new T();
}
}
}
return result;
}
allora si avrebbe incapsulato l'inizializzazione di un 3 dimensionale matrice frastagliata di tipi di riferimento. Ciò consentirebbe di fare,
Foo[][][] foo1 = ThreeDimmer<Foo>(1000, 1000, 500);
Questo permetterebbe di evitare i problemi di frammentazione della memoria di array multidimensionali. Eviterebbe anche other pitfalls and limitations, offrendo invece una matrice più veloce e più flessibile.
Penso che se si compila per 64x si sta andando bene. Penso anche che vai oltre il limite per un oggetto con il primo array. quindi sì, le due istruzioni prendono approssimativamente lo stesso spazio in memoria ma è solo perché si supera il limite per oggetto di .net (almeno per 32x) –
L'uso di "nuovo" lo metterà in pila. Probabilmente funziona quando lo dividi perché non stai più richiedendo 500 milioni di pezzi _contiguous_ "Foo". –
Sei proprio sicuro di aver bisogno di un array pre-allocato di 'Foo'.Spiegare cosa si sta cercando di ottenere usando un array di tale dimensione, ci possono essere modi migliori per gestirlo (forse un dizionario annidato che contiene solo valori popolati è necessario 'Dictionary >>') –