본문 바로가기

IT/Trouble Shoot

Unity - Array 최대 크기

반응형

ArgumentOutOfRangeException : Length * sizeof(T) cannot exceed 2147483647 bytes

 

유니티에서 제공해주는 C# Job System에 대해서 공부하고 연구하다가 문득 그럼 21억개의 float 배열을 처리하는데엔 얼마나 걸릴까란 궁금증을 위해 무식하게 인덱스에 21억을 입력했다.

 

당연하게도 무식한 행위엔 무식한 결과가 나온다. 위와 같은 예외가 뿜어지면서 작동을 안하는데, 한 번 읽어보고 검색도 조금 해보면서 알게 된 사실.

 

배열의 최대길이였다. 원체 큰 값을 처리할 이유가 없어서 몰랐는데 배열도 최대길이가 있으시단 거다.

 

그리고 그 배열의 최대길이는  다음과 같다. (설명을 위해 float형 배열)

int MaxLength = int.MaxValue / sizeof(float);

 

예외를 읽어보면 알 수 있듯 "길이 * (해당 자료형의 크기)는 (int형의 최대값)byte를 넘어갈 수 없습니다."를 지켜야만 할 수 있다.

 

 

그래서, NativeArray<float> a = new NativeArray<float>(536870911, Allocator.TempJob);을 하면 쓸 수 있는가? 에 대해선 별도다.

 

너무 배열을 많게 선언하려 하다보면 결국 그 만한 메모리를 생성하고 확보하다가 터져버린다. 뭐든지 적당한게 좋다.

 

필자는 그래서 10만개로만 테스트 해보았다.

 

 

테스트 방법은 다음과 같다.

(전체 코드 없음 주의)


1. 10만개의 float 배열 A,B,Result를 준비한다. 

2. (길이/나눌량) 을 이용해 한 작업에 분배할 처리량을 정하며, 밑에 있을 모든 작업에 이 규칙을 적용한다. 

3. A와 B에는 각각 다음 식을 적용 해 초기화 한다.

//i는 인덱스이며, 병렬 처리에 따라 완전한 순차적 처리가 아니며 시작 인덱스와 처리할 길이는는 각 작업마다 다를 수 있다.

 A[i] = i >> i;

 B[i] = i << i;

4. 초기화가 마쳐지면 다음 식을 통해 결과 값을 적용한다.

 Result[i] = A[i] + B[i]

5. 덧셈 작업이 끝나면 출력한다.

 Debug.Log(i + " : " + Result[i]);

 


참고로 위에 있는 3,4,5번의 작업은 각각 병렬처리다. 

 

결과부터 말하자면 준비시간이 더길었고 처리 자체는 한 프레임내에 모두 처리되서 시간차를 구하는게 무의미한 일이 될정도로 빠르게 처리되었다. 

 

그리고 2번의 나눌량은 4~16 사이로 적용해보았는데, 왜 이렇게 했냐면 cpu 코어와 스레드를 고려해 어떻게 하는게 좋을까란 실험을 해보려했다.

 

이 것도 결론만 말하자면 너무 빨라서 의미가없었다. 나중에 좀더 큰 단위 혹은 작고 잦은 연산을 고려해서 짜봐야 할 듯 싶다.

반응형