병렬 어레이를 사용하는 것이 좋은시기는 언제입니까?


14

나는 '병렬 배열'또는 목록이라고 부르는 것을 사용하는 코드 (새로운 코드)를 겪었습니다. 의미는 관련 데이터를 포함하고 어레이의 위치 (인덱스)로 연결된 2 개의 어레이가 있음을 의미합니다.

나는 혼란스럽고 모든 종류의 오류가 발생하기 쉽다고 생각합니다. 내가 일반적으로 제안하는 솔루션은 CompanyCompanyId 및 CompanyName 필드로 불리는 객체를 만드는 것 입니다.

매우 실제적인 예 :

List<string> companyNames;
List<int> companyIds;

//...They get populated somewhere and we then process

for(var i=0; i<companyNames.Count; i++)
{
    UpdateCompanyName(companyIds[i],companyNames[i]);
}

이 병렬 배열은 나쁜 습관으로 간주 됩니까?


9
포트란을 작성할 수없는 언어가 발명되지 않았다는 추가 증거.
앤디 망고

3
이와 같은 작업을 수행하면 캐싱 이점이 매우 중요 할 수 있습니다 (링크 목록이 아닌 연속 배열이 필요하지만). "데이터 지향 디자인"과 관련된 게임 프로그래밍에서 다소 인기가 있습니다. 그러나 이것은 귀하의 경우에는 적용되지 않는 것 같습니다. 성능이 중요한 코드를 작성하는 것처럼 보이지 않습니다.
Derek Elkins가 SE

2
@DerekElkins ... 귀하의 의견이 이것을 Fortran 코드와 비교 한 것에 흥미가 있습니다. Fortran의 초기 버전은 사용자 정의 구조에 대한 지원이 없었으며, 관용구가 추가 된 후에도 구조 배열이 아닌 여러 속성 배열을 사용합니다. 그리고 이것은 종종 포트란이 가장 빠른 언어로 여겨지는 이유의 일부로 인정됩니다.
Jules

3
이 질문에 대한 견해 : 많은 기능적 언어가 그러한 목록으로 작업하는 것을 적극적으로 권장합니다. 그것들은 보통 zip이라고하는 함수를 가지고 그것들을 튜플리스트로 변환합니다. 코드는 C #처럼 보입니다. 최신 버전의 C #에는 퍼스트 클래스 튜플에 대한 지원이 추가되었습니다. 따라서 목록을 자동으로 유용한 구조로 만들 수있는 zip 함수를 추가했는지 궁금합니다.
Jules

4
글쎄, 때로는 의도적으로 두 개의 배열을 사용하는 이유가 있지만 모든 경우의 99 %에서 이것을 보았습니다. 유일한 이유는 원래 작성자가 수용 가능한 데이터 구조를 도입하는 게으른 것입니다.
Doc Brown

답변:


23

누군가가 병렬 배열을 사용하는 몇 가지 이유는 다음과 같습니다.

  1. 클래스 나 구조체를 지원하지 않는 언어
  2. 개별 스레드가 열 중 하나만 수정하는 경우 스레드 잠금을 피하려면
  3. 지속성 방법으로 이러한 항목을 별도로 저장하고 재구성하는 경우
  4. 구조가 채워지면 메모리를 덜 소비 할 수 있습니다. (C #에서 이러한 데이터 유형에는 적용되지 않음)
  5. CPU 캐시를 효율적으로 사용하기 위해 데이터의 일부를 가깝게 유지해야하는 경우 (위 코드에서는 도움이되지 않음).
  6. SIMD (Single Instruction Multiple Data) op 코드 사용. (이 코드 또는 문자열에는 적용되지 않습니다)

이 경우이 작업을 수행 해야하는 강력한 이유는 없습니다 ... 그리고 위의 모든 옵션에 더 나은 옵션이 있거나 고급 언어에서는 그렇게 유용하지 않습니다.


3
구조가 채워지면 메모리를 덜 소비 할 수 있습니다. 지능적으로 할당 된 여러 대형 어레이는 어레이 구조보다 적은 메모리를 소비 할 수 있습니다.
Frank Hileman

4
4. CPU 캐시를 효율적으로 사용하기 위해 데이터의 일부를 서로 가깝게 유지해야하는 경우. (드문 경우에 필요합니다.)
Blrfl

@ Frank Hileman, Whilie TheCatWhisperer의 답변이 완전히 정확하다고 생각합니다. 귀하의 의견은 실제로이 접근법을 선택하는 가장 좋은 이유입니다. 메모리 소비가 중요한 경우, 특히 패딩이 많은 경우 구조체 패딩의 메모리 오버 헤드가 중요 할 수 있습니다.
블라디미르 스토 키

대답에 제안을 추가
TheCatWhisperer

다시 (2) 어떻게 지내? 단일 배열의 구조체와 필드 당 잠금으로 프로그램을 작성할 수있는 것처럼 여러 배열과 배열 당 잠금을 사용하여 쉽게 작성할 수 있습니다.
Solomon Slow

7

병렬 배열을 사용하는 것이 유죄였습니다 . 때때로 당신은 구조에 너무 빠져있어서 추상화하는 방법에 대해 생각하고 싶지 않습니다. 추상화는 리팩토링하기가 조금 더 어려울 수 있으므로 실제로 필요한 것을 입증 할 때까지 바로 시작하는 것을 꺼려합니다.

그 시점에서 세부 사항을 추상화하기 위해 리팩토링을 고려해 볼 가치가 있습니다. 종종 내가 싫어하는 가장 큰 이유는 좋은 이름을 생각하기 어렵다는 것입니다.

병렬 배열을 추상화하는 좋은 방법을 볼 수 있다면 매번 그렇게하십시오. 그러나 만지지 말고 자신을 마비시키지 마십시오. 때로는 약간 더러운 코드가 훌륭한 코드를 만들기위한 최고의 디딤돌입니다.


6

이 패턴은 종종라고도 배열의 구조 (구조의 배열에 반대) 및 코드를 벡터화 할 때 매우 유용합니다. 단일 구조에서 실행되는 계산을 작성하고 그 비트를 벡터화하는 대신 SSE 내장 함수를 제외하고 평소처럼 계산을 작성하여 하나가 아닌 4 개의 구조에서 실행되도록합니다. 이것은 일반적으로 더 쉽고 거의 항상 빠릅니다. SoA 형식은 이것을 매우 자연스럽게 만듭니다. 또한 정렬 기능이 향상되어 SSE 메모리 작업이 더 빨라집니다.


예,이 접근 방식은 GPU에서 기계 학습을 수행 할 때 사용됩니다. 많은 개별 예제의 필드를 분리하고 각 필드의 모든 값을 별도의 텐서에 묶은 다음 이러한 텐서를 대량으로 전달하여 예측 목록을 생성하는 것이 일반적입니다.
복원 Monica Monica
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.