2010-07-25 3 views
2

질문 - 인수로 배열을 수신 말하자면, 내가 가진 기능,C# 배열 질문 (분할) 매우 간단

void calc(double[] data) 

방법 "분할"두 개의 하위 어레이에서이 데이터를하고이

같은 하위 기능에 전달 C에서 내가 어떻게없이 C#에서 동일한 작업을 수행하는 방법이

void calc(double * data, int len) 
{ 
    calc_sub(data, len/2); //this one modifies data!! 
    calc_sub(data + len/2, len/2); //this one modifies data too!! 
} 

를 작성합니다 ++ -

calc_sub(data(0, length/2)); 
cals_sub(data(length /2, length /2)); 

난 희망 당신은 아이디어를 얻었다 불분명 한 메모리 복사? 여기에 2 개의 메모리 사본이 필요합니다. 1) 데이터에서 분할 된 데이터 2) calc_sub 3) 분할 된 데이터에서 다시 데이터로! 이것은 시간과 기억의 거대한 낭비입니다!

답변

2

을, 당신은 배열의 어떤 부분에 배열과 반복 소요는 IEnumerable 클래스를 만들 수 있습니다. ArraySegment과 같으나 better입니다.

5

짧은 대답은 하위 배열을 얻으려면 새로운 배열을 만들고 요소를 복사해야한다는 것입니다 ... 아니면 C++를 사용한다면 memcpying이 될 것입니다.

지금 오프셋/카운트 방식을 사용하지 않는 이유는 무엇입니까? calc_sub(blargh[] array)으로 전화 할 경우 calc_sub(blargh[] array, int offset, int count)?

이것은 기본적으로 start/half-pos 요소에 포인터를 전달하고 함수가 배열 요소의 절반 만 작동하도록 알려주는 C# 방식입니다.


거대한 이중 배열로 작업하지 않는 한이 사실에 대해 걱정할 필요가 없습니다. 64 비트 = 8 바이트. 비록 당신이 1000 개의 엘리먼트 배열을 가지고 있다고해도 8000 바이트, ~ 8 kB의 메모리가 있습니다. 이것은 1 초도 안되는 시간 동안 거의 무료가 될 것입니다 ...

이제 가능한 경우 메모리를 절약하는 것이 좋습니다 ,하지만 나는 조기 최적화로 이것을 지배 할 것이다.

또한 배열은 int 또는 string과는 반대로 실제 객체이므로 참조로 전달되므로이 방법이 메모리와 비교할 때 가장 좋습니다. [배열을 복사하지 않습니다. 그것은 배열 객체에 대한 포인터와 같은 것을 제공합니다.]하지만 함수에서 배열을 수정하면 함수 호출 외부에서 전달 된 배열이 수정된다는 점에서 제한적입니다.

+0

"그"접근법을 사용하는 코드 톤. 복사 작품 allways,하지만 거기에 어떤 "똑똑한"해결책? –

+0

퍼포먼스가 문제가되지 않는다면 나는 이것을 묻지 않을 것입니다. –

+0

+1 : 조숙 한 최적화 – surfasb

8

가장 쉬운 아마 LINQs TakeSkip 확장 방법을 사용하고 있습니다 : 무엇을 calc_sub에 따라

int half = data.Length/2; 
double[] sub1 = data.Take(half).ToArray(); 
double[] sub2 = data.Skip(half).ToArray(); 
+0

읽기 쉬운 솔루션이지만 독창적 인 데이터를 두 번 반복 한 결과 컬렉션의 단순한 반복을 초래할 수 있기 때문에 다소 느립니다. 원본 데이터의 크기가 작거나 시간이 중요하지 않은 경우 좋은 읽을 수있는 솔루션입니다. –

+0

빠른가요? CLR 알고,이 물건을 최적화하는 방법? –

+1

나는 항상 읽을 수있는 코드를 작성하고 나중에 성능이 손상되지 않았는지 확인하기 위해로드 테스트를 수행하려고합니다. 이 경우 리팩터링하십시오. –

1

가서이 같은 자신의 부분 배열 기능을 쓰기 :

public static class ArrayExtensions 
{ 
    T[] SubArray<T>(this T[] arr, int startIndex,int count) 
    { 
    var sub = new T[count]; 
    Array.Copy(arr,startIndex,sub,o,count); 
    return sub; 
    } 
} 

을하고 당신이 그것을 좋아 사용할 수 있습니다 : 당신이 calc_sub 방법은 대신 IEnumerable<double>을 만들 수 있다면

void calc(double[] data) 
{ 
    var half = data.Length /2; 
    data.SubArray(0, half)); 
    data.SubArray(half , half)); 
} 
+0

이미 내 'public static class Extentions'에 ... 제 의견으로는 틀림 없습니다. – Warty

+0

생각은 calc_sub은 데이터와 함께 작동 할뿐만 아니라 데이터를 반환한다는 것입니다. –

+0

@ 0xDEAD BEEF,하지만 calc sub는 전달 된 배열에 의해 계산 된 값을 반환합니다. 맞습니까? 우리는 정직하게 calc_sub이 무엇인지 모릅니다. 그래서 우리가 조언을 당신에게 100 % 목표로 삼을 수는 없습니다. 우리는 당신의 상황이 무엇인지 짐작하고 있습니다. – Warty

1

double[]의 경우 확장 메서드를 사용하여 배열의 일부를 반환하는 식을 만들 수 있습니다.

void calc(double[] data) { 
    int half = data.Length/2; 
    calc_sub(data.Take((half)); 
    calc_sub(data.Skip(half)); 
} 

이렇게하면 데이터를 새 배열에 복사 할 필요가 없으므로 식에서 원래 배열의 항목을 반환합니다.

+0

빠른가요? 직접적인 배열 액세스 대신 IEnumberable.value를 호출 ?? –

+0

합리적으로 빠르지 만 직접 액세스만큼 빠르지는 않지만 성능 문제가 있다는 것을 알고 계십니까? –