2015-04-15 93 views
0

我有兩個數組:array1array2。數組的每個對象也是一個數組(2D數組)。以這種方式我多倍他們。所以我如何使用我使用的大陣列dispatch_apply。每次我收到不同的結果都包含正確的結果。也許有人知道如何解決它?dispatch_apply給出錯誤的輸出數據

dispatch_apply([array2 count], queue, ^(size_t j) 
    { 
     k = 0; 
     for (int l = 0; l < [[array1 objectAtIndex:0] count]; l++) { 
      k += [[[array1 objectAtIndex:i] objectAtIndex:l] intValue] * 
        [[[array2 objectAtIndex:j] objectAtIndex:l] intValue]; 
     } 
     kNSNumber = [NSNumber numberWithInt:k]; 
     [multipliedArrayInto replaceObjectAtIndex:j withObject:kNSNumber]; 
    }); 
    [resulArray insertObject:multipliedArrayInto atIndex:i]; 
} 
+0

'你'來自哪裏?除此之外,這看起來充滿了競爭條件。嘗試for或for-each循環,並不需要並行化這種任務。 – diatrevolo

+1

請請將您的Objective-C代碼丟棄並在普通的舊C中執行此操作。Objective-C中不應該這樣做。你的代碼運行速度比應該慢1000倍。並考慮dispatch_apply併發和NSMutableArray不是線程安全的,這是什麼後果。 – gnasher729

回答

1

有兩件事,我可以建議,我打賭其中一個(或兩者)是解決您的問題的首要解決方案。

首先,我會聲明k位於塊的本地,因此不會有覆蓋或不覆蓋的問題。您可能與塊內的kNSNumber有相同的問題。如果您只是使用該NSNumber實例猛衝multipliedArrayInto累加器,那麼您可以刪除kNSNumber,並在其位置使用@(k)(如果只是爲了更易讀)。同樣,確保multipliedArrayIntodispatch_apply之前被聲明,看起來像是一個外循環(其中i來自哪裏)。最後,確保resulArray被實例化,或者在外部for循環之前準備好。

二,是queue一個併發或串行隊列?如果你正在使用dispatch_apply類似於並行執行/枚舉 - 我認爲這很有可能,所以你正在有效地處理「大數組」 - 然後你實際上保證k被覆蓋。如果您將其更改爲串行,則可能按設計工作。如果你想要它是平行的,你需要將你的k累加器的聲明移到塊中,並確保其他變量的聲明也是有意義的。

更新,以反映問題的更新:

@antonytonies理想,在此線程您後續的答案應該被轉移到問題本身,使人們可以按照這個線程更容易。

所以,它看起來像我描述的正是你的問題。

全局隊列都是併發隊列,這意味着(假設)所有的調度塊被一次執行,並且k內容和其它變量得到吹走取決於塊執行的如何的量級。

我已經採取了你的更新(在「回答」您添加),並修改它可能工作:

// I renamed your method, because nameless parameters pain me. This is cosmetic, and doesn't 
// matter for the problem at hand. 
- (NSMutableArray *)multiplicationArrays:(NSMutableArray *)array vector:(NSMutableArray *)vector 
{ 
    // IMHO, you want to set resultArray to nil here. Another option is to set it to nil in the 
    // else case, below. Properties in Objective-C are initalized to nil,0,false,etc; you can 
    // rely on ARC to initialize pointer to objc objects on the stack, too. However, someone 
    // reading this code may or may not know that. IMHO, using the explicitly assignement makes it 
    // clear that you're going to be returning `nil` or an instance of `NSMutableArray`. 
    NSMutableArray *resultArray = nil; 

    if ([[array objectAtIndex:0] count] == [vector count]) { 

    // Nicely done w/ pre-allocating the result array here, so that there's no question 
    // of the indexes matches the results later on. 
    resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]]; 
    for (int i=0; i < [array count]; i++) { 
     [resultArray insertObject:[NSNull null] atIndex:i]; 
    } 

    // 'queue' here is a concurrent queue. This means that you are proclaiming to the runtime 
    // that the blocks being executed are able to operate correctly w/o interference from each 
    // other. This is also thought of in terms of parallel execution: all these blocks may run 
    // **at once**. This *also* means, that you must not share storage between them. 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_apply([array count], queue, ^(size_t j) { 
     // Moved 'result' inside the block. 
     NSInteger result = 0; 

     for (int l = 0; l < [[array objectAtIndex:0] count]; l++) { 
     // These array reads are **NOT** thread safe. They probably don't cause must trouble in 
     // practice, but you may want to reconfigure this. 
     result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l] intValue]; 
     } 

     // The replace of the object into resultArray is **NOT** thread-safe. 
     // This probably hasn't caused you much trouble, since you can guarantee that 
     // you aren't writing at the same index. However, I would strongly suggest to 
     // change this to be thread-safe. 
     [resultArray replaceObjectAtIndex:j withObject:@(result)]; 
    }); 

    } 
    else { 
    NSLog(@"matrix count isn't correspond"); 
    } 

    return resultArray; 
} 

最後:使用蘋果的Accelerate框架,這種解決問題的考慮而已。它可在OSX和iOS上使用,因此您應該涵蓋所有基礎。

+0

我在這個塊之前聲明瞭'k,multipliedArrayInto,resultArray'。我的隊列是'dispatch_queue_t隊列= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);' –

+0

這是同樣的事情,如果我多個2D陣列和向量 –

+0

@antonytonies我更新了我的答案,用你的第二篇文章解釋你必須做的最小改變。正如我所指出的,這仍然不會使您的代碼100%線程安全。 – greymouser

0

這是同樣的事情,如果我多二維數組和矢量

-(NSMutableArray*)multiplicationArraysWithVector:(NSMutableArray *)array :(NSMutableArray *)vector 
{ 
    NSMutableArray* resultArray; 

    if ([[array objectAtIndex:0] count] == [vector count]) 
     { 
      resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]]; 
      for (int i=0; i < [array count]; i++) { 
       [resultArray insertObject:[NSNull null] atIndex:i]; 
      } 

       __block NSInteger result; 

      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
      dispatch_apply([array count], queue, ^(size_t j) 
          { 
           result = 0; 


           for (int l = 0; l < [[array objectAtIndex:0] count]; l++) { 
            result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l]intValue]; 
           } 

           [resultArray replaceObjectAtIndex:j withObject:@(result)]; 
          }); 


    } 
    else 
    { 
     NSLog(@"matrix count isn't correspond"); 
    } 

    return resultArray; 

} 

在這種情況下,我可以得到一個正確或錯誤的數據結果。