Sto ancora cercando di trovare un modo veloce per convertire un array generico di tipo TOutput in un altro array di tipo TInput. Tutti i miei array hanno sempre un tipo di dati numerico, ma poiché C# non ha vincoli di tipo numerico come spesso richiesto, attualmente devo convivere con questo vincolo. I metodi suggeriti, come il casting su un oggetto prima, sembrano rallentare il mio cast tremendamente. Attualmente ho un grande costrutto if/else che controlla il tipo e il cast in un tipo definito usando l'aritmetica del puntatore, ma questo è il modo per gestire il futuro. Parallelamente .Per un buon modo per sbarazzarsi dei puntatori e per accelerare le cose, ma i vincoli generici di C# sembrano essere un problema, ma il problema è ancora presente nel codice sottostante. Ecco il mio codice:Come lanciare un array generico in un altro tipo?
public static OutputType[] Cast<InputType, OutputType>(InputType[] inputArray_in)
{
var aRange = Partitioner.Create(0, inputArray_in.Length);
OutputType[] aResult = new OutputType[inputArray_in.Length];
Parallel.ForEach(aRange, (r) =>
{
for (int i = r.Item1; i < r.Item2; i++)
{
aResult[i] = (OutputType)(inputArray_in[i]);
}
});
return aResult;
}
Esempio:
float[] A = { 0.1f, 0.2f, 0.6f };
int []B = Cast<float, int>(A);
In tutti i casi miei tipi di array sono valori numerici (float, breve, doppio, ...) e la maggior parte del tempo, gli array sono circa Immagini 512x512, ma in una pila di circa 1000 fette in un volume. Vedi qualche possibilità di avere un modo semplice per farlo?
codice di prova
public static class CastTest
{
delegate double[] CastMethod(int[] input);
public static unsafe double[] Cast1(int[] input)
{
int N = input.Length;
double[] output = new double[N];
for (int i = 0; i < N; i++) output[i] = (double)(input[i]);
return output;
}
public static unsafe double[] Cast2(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++, inp++, outp++) *outp = (double)(*inp);
}
return output;
}
}
public static unsafe double[] Cast3(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++) outp[i] = (double)(inp[i]);
}
return output;
}
}
public static unsafe double[] Cast4(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
fixed (int* input_pinned = input)
{
for (int i = 0; i < N; i++) output_pinned[i] = (double)(input_pinned[i]);
}
}
return output;
}
public static unsafe double[] Cast5(int[] input)
{
return Array.ConvertAll<int, double>(input, x => (double)x);
}
public static double[] Cast6(int[] input)
{
var aRange = Partitioner.Create(0, input.Length);
int N = input.Length;
double[] output = new double[N];
Parallel.ForEach(aRange, (r) =>
{
for (int i = r.Item1; i < r.Item2; i++) output[i] = (double)(input[i]);
});
return output;
}
public unsafe static double[] Cast7(int[] input)
{
var aRange = Partitioner.Create(0, input.Length);
int N = input.Length;
double[] output = new double[N];
Parallel.ForEach(aRange, (r) =>
{
fixed (double* output_pinned = output)
{
double* outp = output_pinned + r.Item1;
fixed (int* input_pinned = input)
{
int* inp = input_pinned + r.Item1;
for (int i = r.Item1; i < r.Item2; i++, outp++, inp++) *outp = (double)(*inp);
}
}
});
return output;
}
public unsafe static double[] Cast8(int[] input)
{
var result = (from m in input.AsParallel() select (double)m).ToArray();
return result;
}
public static double[] Cast9(int[] input)
{
return (from m in input select (double)m).ToArray();
}
public static double[] Cast10(int[] input)
{
return (from m in input.AsParallel() select (double)m).ToArray();
}
public static double[] Cast11(int[] input)
{
return new List<double>(input.Select(p => (double)p)).ToArray();
}
static int[] A = new int[100000];
const int runs = 10000;
public static void StartTest()
{
TestMethod("1", Cast1);
TestMethod("2", Cast2);
TestMethod("3", Cast3);
TestMethod("4", Cast4);
TestMethod("5", Cast5);
TestMethod("6", Cast6);
TestMethod("7", Cast7);
TestMethod("8", Cast8);
TestMethod("9", Cast9);
TestMethod("10", Cast10);
TestMethod("11", Cast11);
}
static void TestMethod(string Name, CastMethod method)
{
var timer = Stopwatch.StartNew();
for (int i = 0; i < runs; i++) { double[] res = method(A); }
timer.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", Name, timer.ElapsedMilliseconds));
}
}
Grazie Martin
Può fare un esempio specifico qui di cosa potrebbero essere 'InputType',' OutputType' e 'Tout'? –
Ciao Marc, mi dispiace ho fatto un errore nel codice. Ho fatto un aggiornamento. – msedi
lo fa in linq fa la differenza? (Non sono vicino all'ambiente di sviluppo ma questo è grosso modo il suo significato) var result = (da m in range.AsParallel() select (int) m) .ToArray(); – Peter