我有一个简单的任务,即根据以下规则扩展字符串FX
:
X -> X+YF+
Y-> -FX-Y
在OpenCL中,不支持字符串操作,但使用字符数组。并行扩展此字符串的内核程序如何在openCL中显示?
更多详情: 考虑一下' FX'在下面的python代码中。
axiom = "FX"
def expand(s):
switch = {
"X": "X+YF+",
"Y": "-FX-Y",
}
return switch.get(s, s)
def expand_once(string):
return [expand(c) for c in string]
def expand_n(s, n):
for i in range(n):
s = ''.join(expand_once(s))
return s
expanded = expand_n(axiom, 200)
结果expanded
将是扩展公理' FX' 200次。这是一个相当缓慢的过程,因此需要在openCL上进行并行化。
这个过程产生一个字符串数组,然后我将用它来绘制龙曲线。
下面是我如何想出这样一条龙曲线的例子:这部分并不重要。 OpenCL的扩展是至关重要的部分。
import turtles
from PIL import Image
turtles.setposition(5000, 5000)
turtles.left(90) # Go up to start.
for c in expanded:
if c == "F":
turtles.forward(10)
elif c == "-":
turtles.left(90)
elif c == "+":
turtles.right(90)
# Write out the image.
im = Image.fromarray(turtles.canvas)
im.save("dragon_curve.jpg")
答案 0 :(得分:1)
像这样的递归算法并不特别适合GPU加速,特别是当数据集在每次迭代时改变其大小时。
如果您确实需要迭代地执行此操作,那么挑战在于每个工作项都要知道输出字符串中放置结果的位置。一种方法是为工作组分配输入的特定子字符串,并在每次迭代时,保持输出的每个工作组大小的子字符串中的X和Y总数的计数。从中可以计算出子串在一次迭代中将展开多少,如果累积这些值,您将知道每个子串扩展的输出的偏移量。这是否有效是另一个问题。 : - )
但是,您的算法实际上是可预测的:您可以精确计算最终字符串的初始字符串和迭代次数的大小。使用OpenCL生成此字符串的最佳方法是提出一个非递归函数,该函数在给定M次迭代的情况下分析计算位置N处的字符,然后在每个工作项中调用该函数一次,使用(已知!)final字符串的长度作为工作大小。我不知道是否有可能提出这样的功能,但似乎可能是这样,如果有可能,这可能是在GPU上进行此操作的最有效方法。
似乎这可能是可能的:据我所知,结果将是高度周期性的:
FX
FX+YF+
FX+YF++-FX-YF+
FX+YF++-FX-YF++-FX+YF+--FX-YF+
FX+YF++-FX-YF++-FX+YF+--FX-YF++-FX+YF++-FX-YF+--FX+YF+--FX-YF+
^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^
A* B A B A B A B
据我所知,那些A块都是相同的,B也是如此。 (除了第一个有效位于-1的A之外)因此,您可以完全确定地确定每16个中的14个位置的字符。我强烈怀疑有可能计算出连接它们的+
和-
的模式。如果你想出来,解决方案变得非常简单。
请注意,当你拥有该功能时,你可能甚至不需要将结果放在一个巨大的字符串中:你可以直接用该函数提供绘图算法。