目标C语言 多线程图像处理比单线程慢



我正在Objective-C中处理图像,并尝试了Grand Central Dispatch,结果很糟糕。CPU使用率翻倍,处理图像的时间翻倍。

- (void) processImage:(struct ImageData)image {
    imageData = image;
    [allyMinionManager prepareForPixelProcessing];
    int cores = 4;
    int section = imageData.imageHeight/cores;
    if (section < 1) {
        section = 1;
    }
    dispatch_group_t group = dispatch_group_create();
    for (int i = 0; i < cores; i++) {
        int yStart = section * i;
        int yEnd = yStart + section;
        if (i == cores - 1) {
            yEnd = imageData.imageHeight;
        }
        dispatch_group_enter(group);
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            for (int y = yStart; y < yEnd; y++) {
                uint8_t *pixel = imageData.imageData + (y * imageData.imageWidth)*4;
                for (int x = 0; x < imageData.imageWidth; x++) {
                    [allyMinionManager processPixel:pixel x:x y:y];
                    pixel += 4;
                }
            }
            dispatch_group_leave(group);
        });
    }
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    [allyMinionManager postPixelProcessing:imageData];
}

我在内核之间分离映像,然后等待分派的任务完成。如果我有一个1200x800的图像,每个线程应该处理240,000像素。

Core设置为1:95% CPU使用率,16ms处理时间

Core设置为4:120% CPU使用率,33ms处理时间

你知道为什么表演这么糟糕吗?

(附加问题:当我将编译器优化标志设置为最低时,我的程序中的CPU使用率从45%增加到300%。

我经常发现使用多线程代码通常无法获得理论上期望的好处。存在收益递减的问题。更详细的讨论请参见iOS并发-没有达到任何接近理论最大值的地方。

注意,您可以使用dispatch_group_async,这将消除手动进入和离开组的需要(只有当您正在调度的代码块本身是异步的时,您才需要这样做)。更好的是,如果您在最后等待,您应该考虑使用dispatch_apply,这将完全消除组。

使用dispatch_apply,在Mac上运行,我发现2个线程占用单线程实现的78%的时间,4个线程占用47%的时间,8个线程占用38%的时间。因此,线程数量的增加带来了好处,但它们的回报是递减的。

在iPhone 6+上,当我将线程从一个增加到两个时,我也体验到了类似的性能提高,但当我将线程增加到四个或八个时,我意识到性能没有进一步提高。

所以,底线,我建议尝试dispatch_apply。如果这款设备的性能提升很快就趋于平稳,也不要感到惊讶。所以尝试只使用2个"内核",看看结果是什么。

最新更新