2013-12-18 14 views
5

Tôi đang sử dụng mã nguồn động lực học thủy lực hạt mã nguồn mở .NET 4 của người khác và tôi đang cố gắng chuyển đổi nó thành một dự án Unity mà bạn chỉ có thể đếm được để lên đến .NET 2 tiêu chuẩn. Thật không may, mã sử dụng lớp Parallels (tuyệt vời!) Nhưng ông đã sử dụng một trong những tình trạng quá tải không rõ ràng hơn. Bất cứ ai có thể nhìn thấy một cách tốt để đạt được điều tương tự trong .NET 2 mà không có một hit hiệu suất rất lớn?Chuyển đổi .NET 4 Luồng sang .NET 2

Parallel.For(
     0, 
     _numActiveParticles, 
     () => new Vector2[MAX_PARTICLES], 
     (i, state, accumulatedDelta) => calculateForce(_activeParticles[i], accumulatedDelta), 
     (accumulatedDelta) => 
     { 
      lock (_calculateForcesLock) 
      { 
       for (int i = _numActiveParticles - 1; i >= 0; i--) 
       { 
        int index = _activeParticles[i]; 
        _delta[index] += accumulatedDelta[index]/MULTIPLIER; 
       } 
      } 
     } 
    ); 

tôi nghĩ đây là những gì mã lệnh thực hiện (không ren):

for (int i = 0; i < _numActiveParticles; i++) 
    { 
     Vector2[] temp = new Vector2[MAX_PARTICLES]; 
     temp = calculateForce(_activeParticles[i], temp); 


     for (int k = _numActiveParticles - 1; k >= 0; k--) 
     { 
      int index = _activeParticles[k]; 
      _delta[index] += temp[index]/MULTIPLIER; 
     } 
    } 
+2

Bạn có thể tìm thấy điều này hữu ích http://stackoverflow.com/q/12386686/809009 –

+0

@OndrejJanacek Nhờ đó hữu ích nhưng tôi cũng không chắc chắn 100% những gì phiên bản Parallels đang làm như vậy tôi muốn chắc chắn rằng tôi dịch nó một cách chính xác. – PorcupineRending

+0

Tôi không nghĩ rằng sự hiểu biết của bạn là đúng. Bạn thậm chí không sử dụng biến 'temp' ở bất cứ đâu. Đọc: http://msdn.microsoft.com/en-us/library/ff963547.aspx –

Trả lời

1

mã thứ hai của bạn là không chính xác. Tôi nghĩ rằng mã đúng là như thế này:

var accumulatedDelta= new Vector2[MAX_PARTICLES]; 

for(int i = 0; i < _numActiveParticles; ++i) 
{ 
    accumulatedDelta = calculateForce(_activeParticles[i], accumulatedDelta); 
} 

for (int i = _numActiveParticles - 1; i >= 0; i--) 
{ 
    int index = _activeParticles[i]; 
    _delta[index] += accumulatedDelta[index]/MULTIPLIER; 
} 

Tôi không biết những gì .net2 có và những gì không. Nhưng bạn có thể tự mô phỏng Parallel.For.

giải thích về tình trạng quá tải này của Parallel.For là thế này:

tham số đầu tiên: bắt đầu chỉ số vòng lặp

tham số thứ hai: chỉ số cuối của vòng lặp

tham số thứ ba: một đại biểu rằng sẽ tạo ra nhiệm vụ dữ liệu địa phương . cho mỗi chủ đề mà Parallel.For sử dụng (một nhiệm vụ) đại biểu này sẽ được gọi và trả về localInit dữ liệu.

Tham số thứ tư: một đại biểu hoạt động như nội dung của for. Trong lần thực hiện đầu tiên của đại biểu cơ thể, đại biểu này sẽ truy xuất dữ liệu được tạo bởi đại biểu trước khi sử dụng (localInit). trong mỗi vòng lặp tiếp theo, đại biểu của cơ thể có thể thay đổi localInit và sau đó trả lại điều đó để thực thi cơ thể tiếp theo. Trong lần thực hiện cuối cùng của đại biểu cơ thể, localInit dữ liệu sẽ được chuyển cho người được ủy quyền cuối cùng.

Tham số cuối cùng: một đại biểu khác sẽ được gọi cho mỗi công việc, khi tác vụ hoàn thành công việc của nó. localInit sẽ được chuyển cho đại biểu này. Vì đại biểu này có thể được gọi là đồng thời bởi nhiều tác vụ, bạn phải bảo vệ dữ liệu được chia sẻ của mình.

Edit:

Một phiên bản của ParallelFor có thể như thế này:

public static void ParallerFor<TLocal>(int startIndex, int endIndex, Func<TLocal> initData, Func<int, TLocal, TLocal> body, Action<TLocal> finalizer) 
    { 
     int numThreads = Environment.ProcessorCount; 
     int chunkOffset = ((endIndex - startIndex)/numThreads) + 1; 

     Task[] tasks = new Task[numThreads]; 

     Enumerable.Range(0, numThreads).ToList().ForEach(x => 
      { 
       int start = x * chunkOffset; 
       int end = ((x + 1) * chunkOffset); 
       end = end > endIndex ? endIndex : end; 

       tasks[x] = Task.Factory.StartNew(() => 
       { 
        TLocal init = initData(); 

        for(int i = start; i < end; ++i) 
        { 
         init = body(i, init); 
        } 

        finalizer(init); 
       }); 
      }); 

     Task.WhenAll(tasks).Wait(); 
    } 
+0

Sử dụng lớp Tác vụ để thực hiện lại Parallel.For là loại tâm trạng. Nếu bạn có một cái, bạn cũng có cái kia (cả hai đều là .net 4 và up). –

+0

@ Christian.K Cảm ơn bạn đã đề cập đến. Tôi không biết loại người trợ giúp song song nào '.net 2' có, nhưng thay thế' nhiệm vụ' bằng thủ thuật 'thread' bắt đầu là một công việc đơn giản. – MRB

+0

Bạn có thể kiểm tra msdn. Nó sẽ cho bạn biết. Lưu ý rằng một tác vụ không giống với một chủ đề (ít nhất là sử dụng nhóm luồng và không phải là một chuỗi đơn giản). Nói chung, reimplementing chức năng TPL là không tầm thường để có được chính xác và hiệu quả. Rất nhiều tài liệu về điều đó trên internet. –

Các vấn đề liên quan