Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 减少此Haskell函数中的分配(和工作量)的建议_Performance_Haskell_Optimization_Allocation - Fatal编程技术网

Performance 减少此Haskell函数中的分配(和工作量)的建议

Performance 减少此Haskell函数中的分配(和工作量)的建议,performance,haskell,optimization,allocation,Performance,Haskell,Optimization,Allocation,在我的(更大的)Haskell代码中,我有以下函数(带有一些支持代码,以清楚说明是什么): 导入符合条件的数据。设置为S 导入符合条件的Data.IntMap.Strict作为M 导入数据.Ord 导入数据.幺半群 数据原子=Neg{index::Int} |Pos{index::Int} 推导(等式、Ord、显示、读取) newtype子句=子句{atoms::S.Set Atom} 推导(等式、显示、读取) 实例Ord子句,其中 比较=比较(向下S.size.atoms)比较原子 newty

在我的(更大的)Haskell代码中,我有以下函数(带有一些支持代码,以清楚说明是什么):

导入符合条件的数据。设置为S
导入符合条件的Data.IntMap.Strict作为M
导入数据.Ord
导入数据.幺半群
数据原子=Neg{index::Int}
|Pos{index::Int}
推导(等式、Ord、显示、读取)
newtype子句=子句{atoms::S.Set Atom}
推导(等式、显示、读取)
实例Ord子句,其中
比较=比较(向下S.size.atoms)比较原子
newtype Form=形式{子句::S.Set子句}
推导(等式、Ord、显示、读取)
类型解释=M.IntMap Bool
--利益的功能
解释::解释->表格->可能是布尔
解释interp=evalForm
式中,evalAtom x@(Pos_uuu)=M.lookup(index x)interp
evalAtom x@(负)=非M.lookup(索引x)interp
评估(第x条)
|S.member(Just False)评估=Just False
|已计算==S.singleton(Just True)=Just True
|否则=没有
其中评估=S.map evalAtom x
评估表(表格x)
|S.member(Just True)evaluated=Just True
|已评估==S.singleton(Just False)=Just False
|否则=没有
其中计算值=S.map评估值x
在分析了Haskell程序之后,我发现这个
exploration
函数的分配占我程序中所有分配的近40%(以及CPU工作的40%)


有什么方法可以减少
解释所做的工作量或分配的工作量?这可能会给我带来巨大的性能提升(这是我真正需要的,因为我需要多次运行这段代码进行实验)。

我会用
S.foldr
进行实验

从您的代码中,看起来这些是AND子句,因此我将假设空子句为false

evalClause (Clause x) = S.foldr f (Just False) $ S.map evalAtom x
     where f b@(Just False) _              = b
           f (Just True)    y              = y
           f Nothing        y@(Just False) = y
           f Nothing        y              = Nothing
evalForm
类似

使用列表而不是集合也可能是有益的。在实现时,集合是严格的,并且(我认为)不会触发一些优化,如融合/毁林等。列表是惰性生成的,在这种代码中应该表现得更好

evalClause (Clause x) = foldr f (Just False) . map evalAtom $ S.toList x
     ...

我将尝试使用
S.foldr

从您的代码中,看起来这些是AND子句,因此我将假设空子句为false

evalClause (Clause x) = S.foldr f (Just False) $ S.map evalAtom x
     where f b@(Just False) _              = b
           f (Just True)    y              = y
           f Nothing        y@(Just False) = y
           f Nothing        y              = Nothing
evalForm
类似

使用列表而不是集合也可能是有益的。在实现时,集合是严格的,并且(我认为)不会触发一些优化,如融合/毁林等。列表是惰性生成的,在这种代码中应该表现得更好

evalClause (Clause x) = foldr f (Just False) . map evalAtom $ S.toList x
     ...
观察:

可能Bool
只能有三个可能的值-
仅为False
仅为True

evaluse
evalForm
中的
evaluated
都有类型
Set(可能是Bool)
,可以用适合整数的三位表示

我将定义:

data MaybeBool = Nuthin | JustFalse | JustTrue
  deriving (Eq, Ord, Enum, Bounded, Show, Read)
并更改
intepret
returna
MaybeBool

然后将
评估的
定义为如下位集:

import Data.Bits

evaluated = foldl' combine 0 (map evalAtom (S.toList x))
  where combine s a = s .|. (1 `shiftLeft` fromEnum a)
evaluated
将是一个介于0和7之间的整数,如果
Nutin
在集合中,则设置位0;如果
JustFalse
在集合中,则设置位1;如果
JustTrue
在集合中,则设置位2。这将消除计算中的集合分配。

观察:

可能Bool
只能有三个可能的值-
仅为False
仅为True

evaluse
evalForm
中的
evaluated
都有类型
Set(可能是Bool)
,可以用适合整数的三位表示

我将定义:

data MaybeBool = Nuthin | JustFalse | JustTrue
  deriving (Eq, Ord, Enum, Bounded, Show, Read)
并更改
intepret
returna
MaybeBool

然后将
评估的
定义为如下位集:

import Data.Bits

evaluated = foldl' combine 0 (map evalAtom (S.toList x))
  where combine s a = s .|. (1 `shiftLeft` fromEnum a)

evaluated
将是一个介于0和7之间的整数,如果
Nutin
在集合中,则设置位0;如果
JustFalse
在集合中,则设置位1;如果
JustTrue
在集合中,则设置位2。这将消除计算中的集合分配。

因为您没有给出太多的上下文,所以我真的无法想出任何现成的想法。但是,您可以考虑将<代码>子句< /代码>表示为两个<代码> ItStuts<代码> s,一个用于<代码> NEG <代码>值,一个用于<代码> POS <代码>值。您还应该注意到,
集合
的集合通常很慢,但这更多是由于比较成本而非分配。@d我对
子句
s和
表单
s使用集合的主要动机是希望它们具有唯一的成员资格。是否有一种替代结构我可以使用,它不会有你所描述的关于集合集合缓慢的问题?唯一成员资格?我不知道你的意思。如果一个元素应显示为
Neg
Pos
,但不能同时显示这两个元素,则无法实现这一点。要做到这一点,您应该使用
data Sign=Neg | Pos
,然后使用
IntMap Sign
。由于您没有给出太多的上下文,我真的无法想出任何现成的想法。但是,您可以考虑将<代码>子句< /代码>表示为两个<代码> ItStuts<代码> s,一个用于<代码> NEG <代码>值,一个用于<代码> POS <代码>值。您还应该注意到,
集合
的集合通常很慢,但这更多是由于比较成本而非分配。@d我对
子句
s和
表单
s使用集合的主要动机是希望它们具有唯一的成员资格。是否有一种替代结构我可以使用,它不会有你所描述的关于s的问题