简体   繁体   English

并行或多线程运行haskell操作

[英]run haskell operations in parallel or multithreaded

I have just started learning functional programming and Haskell and am I not even close to understanding the syntax and how it works because it is very different from what I have been used to before (ruby, php, C# or node for instance, which are OOP languages - more or less). 我刚刚开始学习函数式编程和Haskell,我甚至还不了解语法及其工作方式,因为它与我以前使用过的语法(例如,ruby,php,C#或node,它们是OOP)有很大的不同。语言-或多或少)。

I am am trying to put together a small program that checks for solutions for Brocard's Problem or so called Brown Numbers and I first created a draft in ruby, but I discovered that Haskell is much more appropriate for doing mathematical expressions. 我试图将一个小程序组合在一起,以检查Brocard问题的解决方案或所谓的Brown Numbers ,我首先用红宝石创建了草稿,但是我发现Haskell更适合于做数学表达式。 I've asked a question previously and I got an answer pretty quick on how to translate my ruby code to Haskell: 我之前曾问过一个问题,并且很快就将红宝石代码转换为Haskell得到了答案:

results :: [(Integer, Integer)] --Use instead of `Int` to fix overflow issue
results =  [(x,y) | x <- [1..1000], y <- [1..1000] , 1 + fac x == y*y]
    where fac n = product [1..n]

I changed that slightly so I can run the same operation from and up to whatever number I want, because the above will do it from 1 up to 1000 or any hardcoded number but I would like to be able to decide the interval it should go through, ergo: 我稍作更改,因此我可以一直执行相同的操作,直到我想要的任何数字,因为上面的操作可以从11000或任何硬编码的数字进行,但是我希望能够确定应该经历的时间间隔,因此:

pairs :: (Integer, Integer) -> [(Integer, Integer)]
pairs (lower, upper) =  [(m, n) | m <- [lower..upper], n <- [lower..upper], 1 + factorial n == m*m] where factorial n = product [1..n]

The reason I ask this questions is that I was thinking if I could run this operations in parallel (and/or on multiple threads and/or cores) and append the results to the same variable. 我问这个问题的原因是我在考虑是否可以并行(和/或在多个线程和/或内核上)运行此操作并将结果附加到同一变量中。

I have not yet understood the parallel processing in Haskell or the threading model, but in ruby a good example of how the threading model works is something like this : 我尚未了解Haskell或线程模型中的并行处理,但是在ruby中,线程模型如何工作的一个很好的例子是这样的

def func1
  i=0
  while i<=2
    puts "func1 at: #{Time.now}"
    sleep(2)
    i=i+1
  end
end

def func2
  j=0
  while j<=2
    puts "func2 at: #{Time.now}"
    sleep(1)
    j=j+1
  end
end

puts "Started At #{Time.now}"
t1=Thread.new{func1()}
t2=Thread.new{func2()}
t1.join
t2.join
puts "End at #{Time.now}"

And in my case, the func1 and func2 would be the same function results computed on different intervals ( [1..1000] -> [i..j] ). 在我的情况下, func1func2将是在不同时间间隔( [1..1000] -> [i..j] )上计算出的相同函数results

I would appreciate some help with this as I am not capable of doing it myself at this point :) 我很乐意为此提供一些帮助,因为我目前无法自己做:)

Parallel and Concurrent Programming in Haskell has a lot of good information, and async is a good library for this stuff. Haskell中的并行和并发编程有很多很好的信息,而异步是一个很好的库。

At the bottom level though, you'll find forkIO to start a new lightweight thread. 不过,在最底层,您会发现forkIO启动一个新的轻量级线程。

Of course that's concurrency , not deterministic parallelism, parallel is the library for that, and also covered in the book. 当然,这是并发的 ,而不是确定性的并行性, parallel是该类的库,并且在本书中也进行了介绍。

Your example translates to: 您的示例转换为:

import Data.Time.Clock (getCurrentTime)

main = do
    start <- getCurrentTime
    putStr "Started At " >> print start
    _ <- forkIO func1
    _ <- forkIO func2
    end <- getCurrentTime
    putStr "End at " >> print end

func1 = helper "func1" 2

func2 = helper "func2" 1

helper name sleepTime = go 0
 where
    go 3 = return ()
    go n = do
        now <- getCurrentTime
        putStr name >> putStr " at: " >> print now
        threadDelay sleepTime
        go $ succ n

I recommend learning the parallel and/or async libraries mentioned above, though, instead of writing your own threading stuff, at least initially. 但是,我建议学习上述并行和/或异步库,而不是至少在最初时编写自己的线程东西。

Here's a not-so-great example of running tests on 8-ish processors using parallel: 这是一个不太好的示例,使用并行在8-ish处理器上运行测试:

import Control.Parallel.Strategies

factorial = product . enumFromTo 1
pairs (lower, upper) =  map fst . filter snd . withStrategy sparkTest
                     $ [ ((m, n), b)
                       | m <- [lower..upper]
                       , n <- [lower..upper]
                       , let b = 1 + factorial n == m*m
                       ]
sparkTest = evalBuffer 8 $ evalTuple2 rseq rpar

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM