Tôi vẫn đang cố gắng tìm cách nhanh chóng để chuyển đổi một mảng chung loại TOUTput thành một mảng kiểu TInput khác. Tất cả các mảng của tôi luôn là một kiểu dữ liệu số, nhưng vì C# không có ràng buộc kiểu với Số như thường được yêu cầu, tôi hiện đang phải sống với ràng buộc này. Các phương pháp được đề xuất, chẳng hạn như truyền tới một đối tượng trước đây, dường như làm chậm quá trình diễn xuất của tôi. Hiện tại tôi có một cấu trúc if/else lớn để kiểm tra một kiểu và truyền đến một kiểu xác định bằng cách sử dụng số học con trỏ, nhưng đây là cách để xử lý lớn cho tương lai. Parallel.For có vẻ là một cách tốt để loại bỏ các con trỏ và để tăng tốc độ, nhưng vẫn còn các ràng buộc chung của C# dường như là một vấn đề, nhưng vẫn là Tout trong đoạn mã dưới đây là một vấn đề. Dưới đây là mã của tôi:Làm thế nào để đúc một mảng chung thành một loại khác?
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;
}
Ví dụ:
float[] A = { 0.1f, 0.2f, 0.6f };
int []B = Cast<float, int>(A);
Trong mọi trường hợp loại mảng của tôi là giá trị số (float, ngắn, đôi, ...) và hầu hết thời gian, các mảng khoảng Hình ảnh 512x512, nhưng trong một chồng khoảng 1000 lát trong một ổ đĩa. Bạn có thấy bất kỳ cơ hội nào để có một cách thực hiện đơn giản này không?
Kiểm tra Mã
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));
}
}
Cảm ơn bạn Martin
Bạn có thể cho một ví dụ cụ thể ở đây những gì 'InputType',' OutputType' và 'Tout' có thể là gì? –
Xin chào Marc, tôi xin lỗi tôi đã nhầm lẫn trong mã. Tôi đã cập nhật. – msedi
không làm điều đó trong linq tạo sự khác biệt? (Tôi không gần môi trường dev nhưng điều này gần như là ý chính của nó) var result = (từ m trong range.AsParallel() select (int) m) .ToArray(); – Peter