dispatch_apply提供不正确的输出数据

时间:2015-04-15 15:24:13

标签: objective-c grand-central-dispatch dispatch

我有两个数组:array1array2。数组的每个对象也是一个数组(2D数组)。通过这种方式,我多了他们。所以我如何使用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];
}

2 个答案:

答案 0 :(得分:1)

我可以建议有两件事,我敢打赌其中一件(或两件)是解决问题的首要方法。

首先,我会在块中声明k本地,所以毫无疑问你要覆盖它。块内的kNSNumber可能存在同样的问题。如果您只是使用该NSNumber实例进入multipliedArrayInto累加器,您也可以删除kNSNumber,并在其中使用@(k)(如果只是为了更多)可读的)。同样,请确保在multipliedArrayInto之前声明dispatch_apply,看起来像外部for循环(i来自哪里)。最后,确保resulArray被实例化,或者在外部for循环之前准备就绪。

其次,queue是并发队列还是串行队列?如果你正在使用dispatch_apply,就像并行执行for / enumeration一样 - 我认为这很可能,所以你正在处理&#34;大数组&#34;有效 - 然后你实际上保证k被覆盖。如果将其更改为串行,则可以按设计工作。如果你想要它是并行的,你需要在块中移动k累加器的声明,并确保其他变量的声明也是有意义的。

更新以反映问题更新:

@antonytonies理想情况下,你在这个帖子上的后续答案应该移到问题本身,以便人们可以更容易地遵循这个主题。

所以,看起来我所描述的正是你的问题。

全局队列都是并发队列,这意味着(假设)所有调度块一次执行,k和其他变量的内容正在逐渐消失关于块的顺序如何执行。

我已经采取了您的更新(在&#34;答案&#34;您添加了),并将其修改为可能有效:

// 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;
}

最后:考虑使用Apple的Accelerate框架来解决这类问题。它可以在OSX和iOS上使用,因此您应该涵盖所有基础。

答案 1 :(得分:0)

如果我有多个2D数组和向量

,那就是同样的事情
-(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;

}

在这种情况下,我可以获得正确或错误的数据结果。