gpt4 book ai didi

objective-c - 在多个线程中执行任务怎么会比在主线程上顺序执行慢 100 倍呢?

转载 作者:行者123 更新时间:2023-12-03 17:02:56 24 4
gpt4 key购买 nike

我有这个other question of mine我曾询问如何使用 Grand Central Dispatch 将代码从顺序处理转换为并行处理。

我将复制问题文本以使事情变得简单......

<小时/>

我有一个 NSNumber 数组,必须通过 20 次测试。如果一项测试失败,则该数组无效;如果所有测试都通过,则该数组有效。我试图以一种方式来做到这一点,一旦发生第一次故障,它就停止进行其余的测试。如果第三次测试失败,则停止评估其他测试。

每个单独的测试在失败时返回 YES,在正常时返回 NO。

我正在尝试将我拥有的串行处理代码转换为使用中央调度的并行处理,但我无法理解它。

这就是我所拥有的。

首先定义要完成的测试。该数组用于运行测试。

#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;

}

这工作完美,但按顺序执行测试。

在用户的帮助下处理代码后,我使用中央调度获得了此代码:

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

volatile __block int32_t hasFailed = 0;

NSInteger count = [TESTS count];

__block NSArray *numb = [[NSArray alloc] initWithArray:numbers];

dispatch_apply(
count,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^(size_t index)
{
// do no computation if somebody else already failed
if(hasFailed) {
return;
}


SEL selector = NSSelectorFromString(TESTS[index]);

BOOL failed = NO;

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

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

[invocation getReturnValue:&failed];

if(failed)
OSAtomicIncrement32(&hasFailed);
});

return !hasFailed;
}

事件监视器显示核心的使用强度似乎更高,但此代码比按顺序工作的旧代码至少慢 100 倍!

怎么会这样?

最佳答案

如果您调用的方法很简单,那么创建所有这些线程的开销可能会抵消并发带来的任何优势。作为Performing Loop Iterations Concurrently 并发编程指南部分说:

You should make sure that your task code does a reasonable amount of work through each iteration. As with any block or function you dispatch to a queue, there is overhead to scheduling that code for execution. If each iteration of your loop performs only a small amount of work, the overhead of scheduling the code may outweigh the performance benefits you might achieve from dispatching it to a queue. If you find this is true during your testing, you can use striding to increase the amount of work performed during each loop iteration. With striding, you group together multiple iterations of your original loop into a single block and reduce the iteration count proportionately. For example, if you perform 100 iterations initially but decide to use a stride of 4, you now perform 4 loop iterations from each block and your iteration count is 25. For an example of how to implement striding, see “Improving on Loop Code.”

该链接到 Improving on Loop Code演练跨步的示例实现,从而平衡线程数量与每个线程完成的工作量。需要进行一些实验才能找到方法的正确平衡,因此请尝试不同的跨步值,直到获得最佳性能。

在我对 CPU 密集进程的实验中,我发现在执行两个线程时获得了巨大的 yield ,但在那之后它就减少了。它可能会根据您调用的方法中的内容而有所不同。

<小时/>

顺便问一下,您调用的这些方法是做什么的?如果您正在执行任何需要主线程的操作(例如 UI 更新),这也会导致结果出现偏差。为了进行比较,我建议您采用串行示例并将其分派(dispatch)到后台队列(作为单个任务),然后看看通过这种方式可以获得什么样的性能。这样您就可以区分主队列与后台队列相关的问题,以及我上面讨论的线程过多开销问题。

关于objective-c - 在多个线程中执行任务怎么会比在主线程上顺序执行慢 100 倍呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23507721/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com