Nim:具有变异状态的并行环路

Nim: Parallel loop with mutating state

提问人:Peheje 提问时间:10/24/2017 更新时间:10/24/2017 访问量:1219

问:

我是尼姆语的新手。我想通过实现一个简单的遗传算法来学习它,通过将工作分配给 CPU 内核来演化字符串(整数数组 atm):

https://github.com/peheje/nim_genetic

我已经成功地并行创建了“代理”,但无法调用必须改变传递状态的函数“life”:

...

type
Agent* = ref object
    data*: seq[int]
    fitness*: float

...
var pool: seq[Agent] = newAgentsParallel(POPULATION_SIZE)
# Run generations
for gen in 0..<N_GENERATIONS:
    let wheel = createWheel(pool)
    let partitions: seq[seq[Agent]] = partition(pool, N_THREADS)
    parallel:
        for part in partitions:
            echo "spawning"
            spawn life(part, pool, wheel)
    pool = createPool(pool, wheel)
...
proc life(part: seq[Agent], pool: seq[Agent], wheel: seq[float]) =
for a in part:
    if random(1.0) < CROSSOVER_PROP:
        a.crossover(pool, wheel)
    if random(1.0) < MUTATE_PROP:
        a.mutate()
    a.calcFitness()
echo "life done"

CPU 被束缚在 100% 上,似乎 Nim 正在将数据复制到“生命”中,因为 RAM 使用率在“生成”后飙升。在 Nim 手册中,它谈到了并行块:

“生成的 proc 中使用的所有其他复杂位置位置 (spawn f(loc)) 必须在并行期间是不可变的 部分。这称为不可变性检查。目前不是 指定了“复杂位置”的确切含义。我们需要做到这一点 优化!

而且我非常使用它作为可变状态,所以也许这就是 Nim 复制数据的原因?如何绕过仅传递指针?几点:

  • 我想我可以避免变异,而是返回被修改的新实例,但我仍然需要传入池和轮子才能从中读取
  • 如果无法使用 parallel: 语句,我将如何使用线程实现它?
  • random() 线程安全吗?不然呢?
  • 还有什么我可以做的不同吗?例如,更容易解开 FlowVar?

来自 Kotlin 的 Java8 Streams,我感到非常被宠坏了。

并发 引用传递 nim-lang

评论

0赞 Peheje 10/25/2017
更新:通过检查生成的 C 或 CPP 代码,我可以看到 life 函数的包装器 deepCopies 参数 “pool”、“wheel” 和 “part”。我不想要的。代码段: N_NIMCALL(void, lifeWrapper_3iD9bvP7DZjU3JFcD7cH26g_2)(void* thread, void* args) { ...genericSeqDeepCopy((&colontmp_), (((tyObject_Env_nim_geneticdotnim__KeiV9a9cjzNnodvQd0yRpBPA) (args))).part0, (&NTI_827srMGabItaeI6XT9cYzxA_));

答: 暂无答案