Я работаю с изображениями CT, поэтому мне нужно много работать с массивами 3D, но обнаружил, что C# имеет дело с массивами очень медленно. Я написал простой тест BFS, основанный на https://stackoverflow.com/a/1056091:C# медленно работает на массивах?
struct Vector
{
public int X, Y, Z;
}
int width = 512, height = 512, depth = 200;
public static int bfs(int[, ,] matrix)
{
bool[, ,] visited = new bool[width, height, depth];
int sum = 0;
Queue<Vector> queue = new Queue<Vector>();
queue.Enqueue(new Vector { X = 0, Y = 0, Z = 0 });
while (queue.Count > 0)
{
Vector c = queue.Dequeue();
int cx = c.X;
int cy = c.Y;
int cz = c.Z;
sum += matrix[cx, cy, cz];
int x, y, z;
if ((x = cx - 1) >= 0 && !visited[x, cy, cz])
{ queue.Enqueue(new Vector { X = x, Y = cy, Z = cz }); visited[x, cy, cz] = true; }
if ((y = cy - 1) >= 0 && !visited[cx, y, cz])
{ queue.Enqueue(new Vector { X = cx, Y = y, Z = cz }); visited[cx, y, cz] = true; }
if ((z = cz - 1) >= 0 && !visited[cx, cy, z])
{ queue.Enqueue(new Vector { X = cx, Y = cy, Z = z }); visited[cx, cy, z] = true; }
if ((x = cx + 1) < width && !visited[x, cy, cz])
{ queue.Enqueue(new Vector { X = x, Y = cy, Z = cz }); visited[x, cy, cz] = true; }
if ((y = cy + 1) < height && !visited[cx, y, cz])
{ queue.Enqueue(new Vector { X = cx, Y = y, Z = cz }); visited[cx, y, cz] = true; }
if ((z = cz + 1) < depth && !visited[cx, cy, z])
{ queue.Enqueue(new Vector { X = cx, Y = cy, Z = z }); visited[cx, cy, z] = true; }
}
return sum;
}
public static void TestTime<T, TR>(Func<T, TR> action, T obj, int iterations)
{
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; ++i)
action(obj);
Console.WriteLine(action.Method.Name + " took " + stopwatch.Elapsed);
}
static void Main(string[] args)
{
Random random = new Random();
int[, ,] m1 = new int[width, height, depth];
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
for (int z = 0; z < depth; ++z)
m1[x, y, z] = random.Next();
const int iterations = 1;
TestTime<int[, ,], int>(bfs, m1, iterations);
TestTime<int[, ,], int>(bfs, m1, iterations);
}
Это занимает ~ 23 секунд (одна итерация). Скомпилирован с VS2012, «Release» d, оптимизирован. Пытался написать аналогичный код на C++ (с выделенными стеками массивами), он занимает ~ 0,08 сек. DFS (со стеком вместо очереди) работает медленнее. 1D или зубчатые массивы дают почти одинаковые результаты. Я должен отметить, что непрерывный доступ (как в Why are multi-dimensional arrays in .NET slower than normal arrays?) работает нормально, 100 итераций массива [512x512x200] в ~ 26 секунд.
Почему не непрерывный доступ к массиву настолько медленный в C#? Есть ли способ ускорить его?
Пробег в профилировщике и посмотреть, попадаете ли вы в какие-либо «горячие» области. – leppie
http://www.yankeerino.com/cpp_vs_csharp_arrays.bhs –
Вы, кажется, измеряете распределение и очередь и массивы вместе. Что происходит, если вы пишете тесты только для доступа к массиву? – DrKoch