线程嵌套的线程

 夏y儿 发布于 2023-02-06 16:50

我一直在寻找一个类似的问题,但没有任何成功.我不知道如何优化cocoa中的一些代码来使用所有可用的CPU内核(我现在不想使用GPU).下面是简单的代码示例,我的意思是:

int limA = 1000;
int limB = 1000;
unsigned short tmp;
for (int i = 0; i < 10000; i++) {
  for (int a = 0; a < limA; a++) {
    for (int b = 0; b < limB; b++) {
      tmp = [[array objectAtIndex:(a*b)] unsignedShortValue];
      c_array[a*limB+b] += tmp;
    }
  }
}

假设数组和c_array已正确初始化等...但正如您所看到的,如果我们有许多迭代(在这种情况下:10 ^ 10),则执行此代码需要一些时间.我想也许在几个线程中执行此代码很简单,但如何同步c_array?在objective-c中改善此类代码的时间执行的最佳方法是什么?也许它可以这样做,大多数外部for循环的迭代0-2499将在线程1和2500-4999线程2等执行...?我知道这是愚蠢的方式,但我不需要"实时"表现......任何想法?

1 个回答
  • 一些建议:

    对数组进行初始传递以从其对象包装器中提取所有短路:

    short *tmp_array = calloc(limA * limB, sizeof(short));
    int tmp_idx = 0;
    for (NSNumber *num in array) {
        tmp_array[tmp_idx++] = [num unsignedShortValue];
    }
    

    这有几个好处.你从10 ^ 10方法调用到10 ^ 6,你的内部循环停止对编译器不透明(它不能"透视"方法调用),你的内部循环变小,更有可能适合指令缓存.

    尝试线性化访问模式.现在你正在进行"跨步"访问,因为索引每次都会成倍增加.如果您可以重新排列数据,tmp_array以便按顺序处理的元素在数组中也是顺序的,那么您应该获得更好的性能(因为每次访问数组都会加载一个完整的缓存行,大多数处理器都是64字节).

    从并行中获得好处可能很棘手.您可以尝试使用以下命令替换外部循环:

    dispatch_apply(10000, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) {
    
    });
    

    OSAtomicAdd但是在内循环中+ = ,但我怀疑无论如何你的速度将由内存访问控制,并且在混合中添加更多处理器只会导致它们踩到彼此的脚趾(即处理器0加载c_array[1500]所以它知道要添加什么tmp,实际加载覆盖[1500-1531]的缓存行,然后处理器1写入c_array[1512],使整个缓存行无效并强制重新读取它.另外,我很确定你需要在c_array中存储32位值才能做到这一点,因为你将使用OSAtomicAdd32(没有OSAtomicAdd16).

    至少,如果要进行并行化,那么您需要弄清楚如何将工作划分为32个元素c_array(即64个字节)的非重叠块,以便您可以避免争用.划分数组的范围还应该让您避免需要使用原子添加操作.

    (编辑)

    查看an0的答案,找出并行化这个的一些实用建议,而不是讨论为什么天真的并行化不起作用:)

    2023-02-06 16:54 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有