2012-09-06 2 views
2

아래 코드가 작동하는 것처럼 보입니다. 즉, 증분 정수의 하위 목록으로 외부 목록을 채 웁니다.중첩 목록의 병렬 채우기

행운이 있습니까?

"슬롯"을 미리 할당하고 교차하지 않도록주의하십시오.

class Program 
{ 
    static List<List<int>> allLists; 

    static void Main(string[] args) 
    { 
     allLists = new List<List<int>>(553); 

     for (int i = 0; i < 553; i++) 
     { 
      allLists.Insert(i, new List<int>()); 
     } 

     Enumerable.Range(0, 552).AsParallel().ForAll((i) => InsertRange(i)); 
    } 

    static void InsertRange(int index) 
    { 
     allLists[index] = Enumerable.Range(0, 7205).ToList(); 
    } 
} 

하나의 목록이 다른 목록을 지울 위험이 있습니까?

+0

비어있는 목록 만 모두 덮어 쓰게 만드는 이유는 무엇입니까? 왜 당신은'Add()'대신'Insert()'를 사용하고 있습니까? 가장 중요한 것은, 요소가 고정 된 콜렉션을 원한다면 배열 대신에'List'를 사용하는 것입니다. – svick

+0

Insert는 방법이 더 좋습니다. 왜냐하면 한 스레드가 어떻게 든 다른 스레드를 중단하더라도 데이터 손실을 일으키지 않기 때문입니다. – MrFox

+0

@MrFox 1. 코드의 해당 부분은 완전히 동기 적이므로 그 시점에는 다른 스레드가 없습니다. 2. 다음과 같은 이유로'Insert()'가 작동하지 않습니다 : a. 'Insert()'는 확실히 thread-safe가 아닙니다. 비. 리스트의 마지막 위치 다음에'Insert()'할 수 있지만, 그 위치를 넘을 수는 없습니다. – svick

답변

1

배열의 다른 부분에 병렬로 액세스하면 .NET에서 스레드로부터 안전합니다. List<T>은 배열로 뒷받침되기 때문에, 코드가 스레드로부터 안전해야한다고 생각합니다.

그러나 나는 당신이 지나치게 복잡하게 생각한다고 생각합니다. PLINQ를 사용하여 모든 내부 목록을 생성 한 다음 ToArray()을 사용하여 최종 배열을 만들 수 있습니다 (List<T>을 실제로 만들려면 ToList()). PLINQ에는 Range()ToArray() (및 ToList())의 자체 버전이 있으므로이 방법이 더 효율적이라고 생각합니다. 실제로 코드를 가속화 할 내부 목록을 작성 병렬화 때이 모든에만 의미가 있습니다, 물론

allLists = ParallelEnumerable.Range(0, 552) 
    .AsOrdered() 
    .Select(i => Enumerable.Range(0, 7205).ToList()) 
    .ToArray(); 

,하지만 당신은에 의해 그 측정해야합니다 :

그래서, 나는 다음과 같은 코드를 다시 작성할 것 당신 자신.

1

이 예는 InsertRange 방법 내부에 고정한다 잠재적 인 비 스레드 안전한 방법 InsertRange (INT 지수)를 가질 수있다. 그러나 요소의 생성이 여전히 병렬로 수행되어 있는지 확인 :

private static Object settingValue = new Object(); 
static void InsertRange(int index) 
{ 
    // This part can be executed in parallel. 
    List<int> values = Enumerable.Range(0, 7205).ToList(); 

    lock (settingValue) 
    { 
     allLists[index] = values; 
    } 
} 

편집 : 그것은 목록을 작성하는 기회 인덱스 번호에 대한 참조를 할당하는 것이 훨씬 더 많은 시간을 요하기 때문에 당신은 단지 운이 일 수 있었다 작은 하나의 과제는 다른 과제와 정확하게 겹칠 것입니다.

+0

'index'는 로컬 변수이므로 스레드 당 하나 이상의 값을 가져 오지 않을 것이므로 안전하다고 생각했습니다. – user1200984

+0

나는 당신이 나를 의심스럽게 생각한다고 말해야하지만 문제는 또한 목록 코드 자체에있을 수있다. 어쩌면 위험에 처한 유일한시기는 목록이 커질 필요가 있지만 필요한 크기로 목록을 시작하는 경우 일 수 있습니다.내가 테스트하는 유일한 방법은 충돌의 가능성을 높이고 0, 1로 범위를 줄이는 것이며 모든 데이터가 여전히 정확하다면 아마 맞을 것입니다 ... – MrFox

관련 문제