加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

目标c – GCD表现不佳

发布时间:2020-12-16 05:53:07 所属栏目:百科 来源:网络整理
导读:你可能记得,我试图使用GCD来加快我的一些代码,即碰撞检测和解析引擎.但是,我显然做错了,因为我的所有GCD代码都比我的序列号慢得多(1.4x和10x之间).请允许我举个例子:我以气泡排序的方式迭代数组,以确定该数组中对象之间的所有可能的冲突: - (double) detec
你可能记得,我试图使用GCD来加快我的一些代码,即碰撞检测和解析引擎.但是,我显然做错了,因为我的所有GCD代码都比我的序列号慢得多(1.4x和10x之间).请允许我举个例子:我以气泡排序的方式迭代数组,以确定该数组中对象之间的所有可能的冲突:
- (double) detectCollisionsInArray:(NSArray*)objects
{   
    int count = [objects count];
    if (count > 0)
    {       
        double time = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++)
        {
            for (int j = i + 1; j < count; j++)
            {
                /** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
            }
        }

        return CFAbsoluteTimeGetCurrent() - time;
    }

    return 0;
}

相当直截了当,考虑到问题的限制,它似乎表现良好.但是,我想利用每个对象的状态在代码段中不被修改,并使用GCD来并行化这个工作.为此,我正在尝试这样的事情:

- (double) detectCollisionsInArray:(NSArray*)objects
{   
    int count = [objects count];
    if (count > 0)
    {
        NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
        NSBlockOperation* blockOperation = nil;

        double time = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++)
        {
            for (int j = i + 1; j < count; j++)
            {
                void (^workBlock) (void) = ^() 
                {
                    /** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
                };

                if (!blockOperation)
                {
                    blockOperation = [NSBlockOperation blockOperationWithBlock:b];
                }
                else
                {
                    [blockOperation addExecutionBlock:workBlock];
                }
            }
        }

        [opQueue addOperation:blockOperation];
        [opQueue autorelease];

        return CFAbsoluteTimeGetCurrent() - time;
    }

    return 0;
}

任何人都可以帮助我走上正确的轨道,或者提供一个良好的GCD教程的链接?我已经浏览了几个GCD教程,并扫描了所有的文档,我仍然觉得我对这个问题的掌握至关重要.谢谢!

解决方法

有没有理由不使用GCD C API和dispatch_ *系列函数?您对NSOperationQueue的GCD方面没有太多的控制(比如要提交块的队列).另外,我不知道你是否使用iOS,但NSOperationQueue在iOS上并没有使用GCD.这可能是它产生了这么多线程的原因.无论哪种方式,如果直接使用GCD API,您的代码将会更简单和简单:
- (double) detectCollisionsInArray:(NSArray*)objects
{   
  int count = [objects count];
  if (count > 0)
  {
    double time = CFAbsoluteTimeGetCurrent();

    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    for (int i = 0; i < count; i++)
    {
      dispatch_group_async(group,queue,^{
        for (int j = i + 1; j < count; j++)
        {
          dispatch_group_async(group,^{
            /** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
          });
        }
      });
    }
    dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
    dispatch_release(group);
    return CFAbsoluteTimeGetCurrent() - time;
  }
  return 0;
}

您可以使用dispatch_group将所有执行组合在一起,并等待所有执行完成dispatch_group_wait.如果您不想知道块的完成情况,您可以忽略组件部分,只需使用dispatch_async. dispatch_get_global_queue函数将获得3个并发队列之一(低,默认或高优先级),以便将块提交到.你不必担心限制线程数或任何类似的事情. GCD调度程序应该为你做所有这些.只要确保提交到一个并发队列,它可以是3个全局队列之一,或者通过将DISPATCH_QUEUE_CONCURRENT传递给dispatch_queue_create创建的队列(这可以从OS X 10.7和iOS 5.0开始).

如果您在每个块中执行一些文件I / O或对某些其他资源征税,则可能需要在GCD中进行统计,并一次限制要提交到队列的块数.这将与限制NSOperationQueue中的并发操作计数具有相同的效果.您可以使用GCD信号量来做到这一点:

- (double) detectCollisionsInArray:(NSArray*)objects
{   
  int count = [objects count];
  if (count > 0)
  {
    double time = CFAbsoluteTimeGetCurrent();

    dispatch_group_t group = dispatch_group_create();
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    for (int i = 0; i < count; i++)
    {
      dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
      dispatch_group_async(group,^{
        for (int j = i + 1; j < count; j++)
        {
          dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
          dispatch_group_async(group,^{
            /** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
            dispatch_semaphore_signal(semaphore);
          });
        }
        dispatch_semaphore_signal(semaphore);
      });
    }
    dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
    dispatch_release(group);
    dispatch_release(semaphore);
    return CFAbsoluteTimeGetCurrent() - time;
  }
  return 0;
}

一旦你得到它的悬挂,GCD是非常简单的使用.我现在使用它在我的代码.

Can anyone help to put me on the right track and perhaps provide a link to a good GCD tutorial?

运行,不要走到Mike Ash’s blog.他的GCD系列是我看到的最清晰和最简洁的,只需要你大约30分钟来阅读整个事情.苹果的WWDC视频从2010年的GCD和块也不错.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读