2015-01-29 4 views
3

CT 이미지 작업 중이므로 3D 배열을 많이 사용해야하지만 C#에서는 배열이 매우 느립니다.배열에 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 초 (하나의 반복) : 나는 https://stackoverflow.com/a/1056091에 따라 간단한 BFS 테스트를 썼다. VS2012와 함께 컴파일 된 "Release"d. 비슷한 C++ 코드 (스택 할당 배열 사용)를 작성하려고하면 ~ 0.08 초가 걸립니다. DFS (대기열 대신 스택 사용)가 느리게 실행됩니다. 1D 또는 들쭉날쭉 한 배열은 거의 동일한 결과를 제공합니다. 연속 액세스 (Why are multi-dimensional arrays in .NET slower than normal arrays?에서와 같이)가 ~ 26 초 안에 [512x512x200] 배열의 100 반복을 잘 실행한다는 점에 유의해야합니다.

C#에서 비 연속 배열 액세스가 너무 느린 이유는 무엇입니까? 속도를 높이는 방법이 있습니까?

+5

프로파일 러에서 실행하고 '뜨거운'영역을 발견했는지 확인하십시오. – leppie

+3

http://www.yankeerino.com/cpp_vs_csharp_arrays.bhs –

+2

당신은 할당과 대기열 및 배열을 함께 측정하는 것 같습니다. 배열 액세스에 대한 벤치 마크를 작성하면 어떻게됩니까? – DrKoch

답변

0

list + struct를 사용하여 도움이되었는지 확인했습니다. 그것은 시간을 절반으로 줄였습니다. 단일 차원을 사용하고 인덱서를 손으로 곱하기 위해 다차원 배열을 변경했습니다. 어떤 것이 든, 그것은 그것을 더욱 악화 시켰습니다.

struct Q 
{ 
    public int X, Y, Z; 
} 
public static int bfs(int[, ,] matrix) 
{ 
    int d1 = matrix.GetLength(0), d2 = matrix.GetLength(1), d3 = matrix.GetLength(2); 
    var visited = new bool[d1, d2, d3]; 
    int sum = 0; 
    var q = new List<Q>(); 
    q.Add(new Q()); 
    while (q.Count > 0) 
    { 
     var last = q[q.Count - 1]; 
     q.RemoveAt(q.Count - 1); 
     int cx = last.X; 
     int cy = last.Y; 
     int cz = last.Z; 
     sum += matrix[cx, cy, cz]; 
     int x, y, z; 

     if ((x = cx - 1) >= 0 && !visited[x, cy, cz]) 
     { q.Add(new Q{X = x, Y = cy, Z = cz}); visited[x, cy, cz] = true; 
... 
+0

구조체를 사용하는 것이 더 낫다는 것을 인정합니다. 그러나 적어도 100x 속도 향상을 원합니다. – MykolasB

+0

BTW, 귀하의 목록은 DFS를 모방합니다. DFS는 더욱 악화됩니다 (어레이 액세스 문제임). 스택을 목록으로 변경하면 시간에 영향을주지 않습니다. – MykolasB

+0

struct로 코드를 시험해 보았는데, 결과가 나 빠졌습니다. 하지만 불평 때문에 제 질문을 업데이트 할게요. – MykolasB

관련 문제