CGD:在drawRect中同时在块/每行上绘制屏幕

时间:2014-02-19 15:06:50

标签: grand-central-dispatch

我想在几天前晚上写一些傻事,我想我会在模拟器上观看元素的动画,只是为了放松。但事实证明,这让我在过去的两天里一直很头疼。

背景

我以为我会在320 X 480的屏幕上的每个像素上画一个随机字母。 我将有一个填充26个字母的数组,并使用arc4Random % 26提取随机字母。

首先,我使用UIGraphicsBeginImageInContextWithOptions并将图像添加到图像视图中,该视图将添加为我视图的子视图。

完全没问题。

然后我意识到,为什么要等?让我们做一个2 for循环(外部:480 - >内部:320) 一旦第一个内部循环结束,在dispatch_async中发送该数组并在drawRect中绘制,然后在下一次迭代完成时,将其发送到另一个dispatch_async,依此类推,直到两个循环饰面。

我的痛苦从此开始/后...............

原因:

for-loop太紧,太快了。因此,在发送包含320个元素的数组之后,我最终在dispatch_async内和for内部for循环中包装2 for循环。

但后来我意识到:通过利用sleep(1);,它想要更快地绘制。实际上,这比完全不使用sleep(1)所需的时间更长。超过25秒。

所以,我继续尝试使用GCD并在只有3200个插槽可用之前创建一个,然后才将semaphore中的数组发送到dispatch_async;

问题:

比赛条件。我会得到意想不到的数组超出界限错误。错误不一致;有时它会发生在以后,有时会更快。我认为这与正确使用drawRect无关。

所以我的问题是:

我知道这可以通过CGD进行微调和解决。但我只是不知道如何。我在我的智慧结束。

我真正想要的是能够更新屏幕的绘图而不是等待整个事情被绘制。要么在屏幕上用点显示一个点,要么通过chuck卡住而不必调用GCD,但最好是调用setNeedsDisplay

我以为我会剖析绘图元素的各个部分,并将每个部分发送到自己的dispatch_async,每个部分都负责仅绘制其部分,并且由于同时运行,它将在屏幕上快速渲染绘图。

但是,我再一次出于想法而结束了沮丧。

setNeedsDisplayinRect

至于信号量版本,我只需在create和signal中设置一个大数字来调用for(int y = 0; y < 480; y++) { for(int x = 0; x < 320; x++) { //get a random letter here and insert it into the array (myArray) } dispatch_async(myQueue, ^ { dispatch_async(dispatch_async_get_main_queue(),^ { [self.myView processRowDrawing:myArray]; } } [myArray removeAllObjects]; //as mentioned: I tried to put a sleep() here because the loop is faster the the drawing } - (void)processRowDrawing:(NSMutableArray*)array { for(x = 0; x < array.count; x++) { //cell here `setNeedsDisplayInRect:` to draw a row } } 但是由于绘图比for循环慢,所以它没有帮助。

是否可以通过[self.myView processRowDrawing:myArray];以一种漂亮而优雅的方式解决这个问题,方法是同时对绘图部分进行分区并将其发送到GCD并让部件在屏幕上逐位显示而不是等待它作为一个整体?

逐行或网格逐格看到它们被绘制?同样,我想在这里使用drawRect

一直在失眠。请指教。

P.S。我已经尝试过使用GCD了。

1 个答案:

答案 0 :(得分:1)

这种情况不太可能在并行性方面变得更快。让我们来探索一下......

让我们在简单的单线程案例中分解正在这里完成的“工作”。你在320 * 480网格中的每个像素中绘制了26个字母中的一个(即153,600次)。这没有任何意义,但让我们一起运行它。除非您没有提及其他内容,否则CoreText将缓存渲染任何这些字母时第一次呈现26个字形中的每个字形的所有设置成本。这意味着在第一次渲染之后渲染每个字母的边际成本是不变的。当你将最后一个字母渲染到最后一个像素时,你将一个完全渲染的320 * 480位图移交给UIKit进行显示,你就完成了。这笔费用与这次讨论无关。我们将单个字母的平均边际成本称为一个像素 A 。单线程机箱可以使用的最短时间为153,600 * A

现在让我们讨论并行化这个渲染所涉及的内容。让我们说把它分成两个320 x 240像素的瓷砖。在这种情况下,您希望整个任务将花费153,600 * A / 2秒。但是,并行化此工作流程还需要其他成本。就在我的头顶:

  1. 调度/切换到这些任务所需的时间
  2. 为每个并行背景渲染设置图形上下文所需的时间
  3. 将单独的图块组合到与视图对应的单个纹理中所需的时间。
  4. 我的猜测是长杆将会是#3。为了使并行化显示任何增益,这些额外成本总共必须小于153,600 * A / 2秒。仅划分为两个区块会产生绝对最小的开销。任何进一步的细分只会增加开销量。如果将它分成两个图块并不是更快,当然没有多于两个的图块会更快。

    您似乎假设渲染字母的成本使并行性的开销相形见绌。我怀疑你是错的。