成本中心适用于通用派生实例吗?

huangapple go评论68阅读模式
英文:

Cost centres for Generic-derived instances?

问题

根据+RTS -p所继承的时间,我的执行时间的90%用于运行基于Genericinstance MyClass MyType定义,递归地针对100多个类型/实例运行一次类。我已经尝试让GHC告诉我这些细节,以找出哪些实例较慢,或哪些实例被更频繁地调用,以便我可以手动优化它们。

然而,即使使用-fprof-auto-calls,我似乎无法让GHC在这些函数上放置成本中心。

我该怎么做才能在每个类型类实例函数上获得调用中心,而不仅仅是整个顶层内容,以便我知道在每个实例中花费了多少时间?

使用GHC 9.2.4。

英文:

According to +RTS -p time inherited, 90% of my execution time is spent running a Generic based instance MyClass MyType definitions, for a single class recursively over 100+ types/instances. I've tried getting GHC to tell me the details of that, to figure out which instances are slow, or which instances are called more often, so I can go and hand-optimize those.

However, I can't seem to get ghc to put cost centres on these functions even with -fprof-auto-calls.

What can I do to get call centres on each type class instance function, rather than just the whole top-level thing as one, so I know how much time is spent in each one?

Using ghc 9.2.4.

答案1

得分: 1

以下是翻译好的部分:

如果您有一个典型的通用函数设置,其中包括用于处理表示的类,其实例执行所有实际工作:

class GSlow f where
  gslow :: f a -> Int

一个独立的类型类用于通用函数本身:

class Slow a where
  slow :: a -> Int
  default slow :: (Generic a, GSlow (Rep a)) => a -> Int
  slow = defaultSlow

defaultSlow :: (Generic a, GSlow (Rep a)) => a -> Int
defaultSlow = gslow . from

用于将控制从一个数据类型传递到另一个数据类型的K1字段的实例:

instance Slow c => GSlow (K1 i c) where
  gslow (K1 x) = ... slow x ...

以及一堆空实例用于您的100+数据类型:

instance Slow Type1
instance Slow Type2
等等

然后,最简单的方法是使用搜索和替换将空的instance Slow替换为:

instance Slow Type1 where slow = defaultSlow
instance Slow Type2 where slow = defaultSlow

使用-fprof-auto,您应该为每个类型特定的slow = defaultSlow函数获得一个调用中心,这将使您能够将GSlow实例中的工作归因于各个数据类型。

英文:

If you have a typical generic function setup with a class for processing the representation whose instances do all the actual work:

class GSlow f where
  gslow :: f a -> Int

a separate type class for the generic function itself:

class Slow a where
  slow :: a -> Int
  default slow :: (Generic a, GSlow (Rep a)) => a -> Int
  slow = defaultSlow

defaultSlow :: (Generic a, GSlow (Rep a)) => a -> Int
defaultSlow = gslow . from

an instance for fields K1 that passes control from one data type to the other:

instance Slow c => GSlow (K1 i c) where
  gslow (K1 x) = ... slow x ...

and a whole bunch of empty instances for your 100+ data types:

instance Slow Type1
instance Slow Type2
etc.

then, by far, the easiest thing to do is to search and replace your empty instance Slows with:

instance Slow Type1 where slow = defaultSlow
instance Slow Type2 where slow = defaultSlow

With -fprof-auto, you should get a call center for every type-specific slow = defaultSlow function which should allow you to attribute the work in the GSlow instances to individual data types.

huangapple
  • 本文由 发表于 2023年1月9日 00:48:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75049616.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定