将代码转换为Grand Central Dispatch [英] Transforming a code to Grand Central Dispatch

查看:121
本文介绍了将代码转换为Grand Central Dispatch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个NSNumbers数组,必须通过20个测试。如果一个测试失败,数组无效,如果所有测试通过,数组有效。我试图做的方式,只要第一个故障发生,它停止做剩余的测试。如果第三次测试发生故障,那么停止评估其他测试。

I have an array of NSNumbers that have to pass thru 20 tests. If one test fails than the array is invalid if all tests pass than the array is valid. I am trying to do it in a way that as soon as the first failure happens it stops doing the remaining tests. If a failure happens on the 3rd test then stop evaluating other tests.

我试图将我已经是串行处理的代码转换为并行处理与大中央调度

I am trying to convert the code I have that is serial processing, to parallel processing with grand central dispatch, but I cannot wrap my head around it.

这是我所拥有的。

测试要做。此数组用于运行测试。

First the definition of the tests to be done. This array is used to run the tests.

每个测试在失败时返回YES,在确定时返回NO。

Every individual test returns YES when it fails and NO when it is ok.

#define TESTS  @[         \
    @"averageNotOK:",     \
    @"numbersOverRange:", \
    @"numbersUnderRange:",\
    @"numbersForbidden:", \
    // ... etc etc
    @"numbersNotOnCurve:"]


- (BOOL) numbersPassedAllTests:(NSArray *)numbers {

  NSInteger count = [TESTS count];

  for (int i=0; i<count; i++) {

    NSString *aMethodName = TESTS[i];

        SEL selector = NSSelectorFromString(aMethodName);

        BOOL failed = NO;

        NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];

        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        [invocation setSelector:selector];
        [invocation setTarget:self];
        [invocation setArgument:&numbers atIndex:2];
        [invocation invoke];


        [invocation getReturnValue:&failed];

        if (failed) {
          return NO;
        }
  }
  return YES;

}

这完全可以顺序执行测试。

This work perfectly but perform the tests sequentially.

如何执行这些测试并行执行所需的较少的测试?

How do I do that perform these tests in parallel executing the less amount of tests as needed?

推荐答案

我假设你发现 dispatch_apply 这是平凡的。你已经意识到它不能提前退出。因此问题。

I assume you've spotted dispatch_apply which is the trivial parallel for. You've realised it can't do an early exit. Hence the question.

恐怕答案是你需要为自己做一些簿记,但幸运的是,这不应该太难。为了避免重复你所有的,假装我把你的循环中的东西变成了:

I'm afraid the answer is you'll need to do some bookkeeping for yourself, but luckily it shouldn't be too hard. To avoid repeating what you've got, pretend I'd turned the stuff inside your loop into:

BOOL failedTest(int);

所以你的连续循环看起来像:

So your serial loop looks like:

for (int i=0; i<count; i++) {

    if(failedTest(i))
      return NO;
}

return YES;

然后您可以:

#import <libkern/OSAtomic.h>

volatile __block int32_t hasFailed = 0;
dispatch_apply(
    count, 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), 
    ^(size_t i)
    {
        // do no computation if somebody else already failed
        if(hasFailed) return;
        if(failedTest(i))
            OSAtomicIncrement32(&hasFailed);
    });

return !hasFailed;

所以它会继续开始测试,直到其中一个先前失败。 OSAtomicIncrement32 只是确保原子性,而不需要互斥。它通常会变成一个便宜的单指令。你可以放弃使用 BOOL 作为原子性不是真的会是一个问题,但为什么不只是正确地做?

So it'll keep starting tests until one of them has previously failed. The OSAtomicIncrement32 just ensures atomicity without requiring a mutex. It'll usually turn into a cheap single instruction. You could get away with just using a BOOL as atomicity isn't really going to be a problem but why not just do it properly?

EDIT:也可以直接使用 @selector 创建一个选择器数组,而不是使用 NSSelectorFromString 有一个字符串数组,以节省查找时间。如果你的测试真的很便宜,那么考虑通过 dispatch_apply 做,部分串行,部分并行,例如 count / 10 调度并让每个调度做10次测试。否则GCD只会发出 count 个块的实例,并且发出具有相关的成本。

also, you could just use @selector directly and create an array of selectors rather than using NSSelectorFromString with an array of strings, to save lookup time. If your tests are really cheap then consider doing them part serial, part parallel by having the dispatch_apply do, say, count/10 dispatches and having each dispatch do 10 tests. Otherwise GCD will just issue count instances of the block and issuing has an associated cost.

这篇关于将代码转换为Grand Central Dispatch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆