在模拟中控制内存分配/GC?

2024-01-08

我在弄清楚如何减少运行在模拟中的内存使用和 GC 时间时遇到了一些麻烦State单子。目前我必须运行编译后的代码+RTS -K100M为了避免堆栈空间溢出,GC 统计数据非常可怕(见下文)。

以下是相关代码片段。完整的工作 (GHC 7.4.1) 代码可以在以下位置找到http://hpaste.org/68527 http://hpaste.org/68527.

-- Lone algebraic data type holding the simulation configuration.
data SimConfig = SimConfig {
        numDimensions :: !Int            -- strict
    ,   numWalkers    :: !Int            -- strict
    ,   simArray      :: IntMap [Double] -- strict spine
    ,   logP          :: Seq Double      -- strict spine
    ,   logL          :: Seq Double      -- strict spine
    ,   pairStream    :: [(Int, Int)]    -- lazy (infinite) list of random vals
    ,   doubleStream  :: [Double]        -- lazy (infinite) list of random vals
    } deriving Show

-- The transition kernel for the simulation.
simKernel :: State SimConfig ()
simKernel = do
    config <- get
    let arr   = simArray      config
    let n     = numWalkers    config
    let d     = numDimensions config
    let rstm0 = pairStream    config
    let rstm1 = doubleStream  config
    let lp    = logP          config
    let ll    = logL          config

    let (a, b)    = head rstm0                           -- uses random stream    
    let z0 = head . map affineTransform $ take 1 rstm1   -- uses random stream
            where affineTransform a = 0.5 * (a + 1) ^ 2


    let proposal  = zipWith (+) r1 r2
            where r1    = map (*z0)     $ fromJust (IntMap.lookup a arr)
                  r2    = map (*(1-z0)) $ fromJust (IntMap.lookup b arr)

    let logA = if val > 0 then 0 else val
            where val = logP_proposal + logL_proposal - (lp `index` (a - 1)) - (ll `index` (a - 1)) + ((fromIntegral n - 1) * log z0)
                  logP_proposal = logPrior proposal
                  logL_proposal = logLikelihood proposal

    let cVal       = (rstm1 !! 1) <= exp logA            -- uses random stream

    let newConfig = SimConfig { simArray = if   cVal
                                           then IntMap.update (\_ -> Just proposal) a arr
                                           else arr
                              , numWalkers = n
                              , numDimensions = d
                              , pairStream   = drop 1 rstm0
                              , doubleStream = drop 2 rstm1
                              , logP = if   cVal
                                       then Seq.update (a - 1) (logPrior proposal) lp
                                       else lp
                              , logL = if   cVal
                                       then Seq.update (a - 1) (logLikelihood proposal) ll
                                       else ll
                              }

    put newConfig

main = do 
    -- (some stuff omitted)
    let sim = logL $ (`execState` initConfig) . replicateM 100000 $ simKernel
    print sim

就堆而言,配置文件似乎暗示System.Random功能,除了(,),是记忆的罪魁祸首。我无法直接包含图像,但您可以在此处查看堆配置文件:https://i.stack.imgur.com/ZMNDA.png https://i.stack.imgur.com/ZMNDA.png.

我不知道如何进一步减少这些东西的存在。随机变量是在外部生成的Statemonad(以避免在每次迭代时分割生成器),我相信唯一的实例(,) inside simKernel当从惰性列表中取出一对时出现(pairStream)包含在模拟配置中。

包括GC在内的统计数据如下:

  1,220,911,360 bytes allocated in the heap
     787,192,920 bytes copied during GC
     186,821,752 bytes maximum residency (10 sample(s))
       1,030,400 bytes maximum slop
             449 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0      2159 colls,     0 par    0.80s    0.81s     0.0004s    0.0283s
  Gen  1        10 colls,     0 par    0.96s    1.09s     0.1094s    0.4354s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    0.95s  (  0.97s elapsed)
  GC      time    1.76s  (  1.91s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    2.72s  (  2.88s elapsed)

  %GC     time      64.9%  (66.2% elapsed)

  Alloc rate    1,278,074,521 bytes per MUT second

  Productivity  35.1% of total user, 33.1% of total elapsed

同样,我必须增加最大堆栈大小才能运行模拟。我知道某个地方一定有一个大重击……但我不知道在哪里?

在这样的问题中,如何改进堆/栈分配和 GC?我如何识别 thunk 可能在哪里堆积?是使用Statemonad 这里被误导了吗?

--

UPDATE:

编译时我忽略了查看探查器的输出-fprof-auto。这是该输出的头部:

COST CENTRE                       MODULE                             no.     entries  %time %alloc   %time %alloc

MAIN                              MAIN                                58           0    0.0    0.0   100.0  100.0
 main                             Main                               117           0    0.0    0.0   100.0  100.0
  main.randomList                 Main                               147           1   62.0   55.5    62.0   55.5
  main.arr                        Main                               142           1    0.0    0.0     0.0    0.0
   streamToAssocList              Main                               143           1    0.0    0.0     0.0    0.0
    streamToAssocList.go          Main                               146           5    0.0    0.0     0.0    0.0
  main.pairList                   Main                               137           1    0.0    0.0     9.5   16.5
   consPairStream                 Main                               138           1    0.7    0.9     9.5   16.5
    consPairStream.ys             Main                               140           1    4.3    7.8     4.3    7.8
    consPairStream.xs             Main                               139           1    4.5    7.8     4.5    7.8
  main.initConfig                 Main                               122           1    0.0    0.0     0.0    0.0
   logLikelihood                  Main                               163           0    0.0    0.0     0.0    0.0
   logPrior                       Main                               161           5    0.0    0.0     0.0    0.0
  main.sim                        Main                               118           1    1.0    2.2    28.6   28.1
   simKernel                      Main                               120           0    4.8    5.1    27.6   25.8 

我不确定如何准确解释这一点,但是随机双打的惰性流,randomList,让我皱眉。我不知道如何改进。


我已经用一个工作示例更新了 hpaste。看起来罪魁祸首是:

  • 缺少三个严格注释SimConfig字段:simArray, logP and logL


    data SimConfig = SimConfig {
            numDimensions :: !Int            -- strict
        ,   numWalkers    :: !Int            -- strict
        ,   simArray      :: !(IntMap [Double]) -- strict spine
        ,   logP          :: !(Seq Double)      -- strict spine
        ,   logL          :: !(Seq Double)      -- strict spine
        ,   pairStream    :: [(Int, Int)]    -- lazy
        ,   doubleStream  :: [Double]        -- lazy 
        } deriving Show
  
  • newConfig从未被评估过simKernel循环由于State懒惰。另一种选择是使用严格的State代替单子。

    put $! newConfig
    
  • execState ... replicateM还构建了 thunks。我最初用一个替换它foldl'并移动了execState进入折叠,但我想交换replicateM_是等价的并且更容易阅读:

    let sim = logL $ execState (replicateM_ epochs simKernel) initConfig
    --  sim = logL $ foldl' (const . execState simKernel) initConfig [1..epochs]
    

并打了几个电话mapM .. replicate已替换为replicateM。特别值得注意的是consPairList它大大减少了内存使用量。仍有改进的空间,但最容易实现的目标涉及 unsafeInterleaveST...所以我停了下来。

不知道输出结果是否是你想要的:



fromList [-4.287033457733427,-1.8000404912760795,-5.581988678626085,-0.9362372340483293,-5.267791907985331]
  

但以下是统计数据:



     268,004,448 bytes allocated in the heap
      70,753,952 bytes copied during GC
      16,014,224 bytes maximum residency (7 sample(s))
       1,372,456 bytes maximum slop
              40 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0       490 colls,     0 par    0.05s    0.05s     0.0001s    0.0012s
  Gen  1         7 colls,     0 par    0.04s    0.05s     0.0076s    0.0209s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    0.12s  (  0.12s elapsed)
  GC      time    0.09s  (  0.10s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    0.21s  (  0.22s elapsed)

  %GC     time      42.2%  (45.1% elapsed)

  Alloc rate    2,241,514,569 bytes per MUT second

  Productivity  57.8% of total user, 53.7% of total elapsed
  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在模拟中控制内存分配/GC? 的相关文章

  • Haskell 入门

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 几天来 我一直试图理解 Haskell 中的函数式编程范例 我通过阅读教程和观看截屏视频
  • Haskell Stack 从 github 安装包依赖项

    是否可以使用 Haskell 堆栈从 github 安装软件包的版本 例如在一个 cabal or a stack yaml文件 如何在 git repo branch revision 上指向依赖项 对于堆栈 The 的文档stack y
  • 如何在C++中生成高精度的随机双数?

    我正在尝试生成一系列高精度的双随机数 例如 0 856365621 小数点后有 9 位数字 我从网上找到了一些方法 但是 它们确实生成了双随机数 但精度没有我要求的那么好 只有小数点后6位 那么 我可以知道如何实现我的目标吗 在 C 11
  • : 中缀运算符在 Haskell 中的作用是什么?

    我正在阅读Haskell 简要介绍 http www haskell org tutorial index html 这不是那么温和 并且它反复使用 操作符而不直接解释它的作用 那么 它到底有什么作用呢 是 前置 运算符 x xs 返回一个
  • 使用带有终结器的 C++/CLI 定义类时 C# 中的内存泄漏

    当我在 C CLI DLL 中实现一个类时 public ref class DummyClass protected DummyClass some dummy code std cout lt lt hello lt lt std en
  • Linq2sql:获取具有权重的随机元素的有效方法?

    Byt 可以说我有一个整数权重 即权重为 10 的元素被选择的概率是权重为 1 的元素的 10 倍 var ws db WorkTypes Where e gt e HumanId null e SeoPriority 0 OrderBy
  • 为什么 ZipList 不是 List 的默认应用实例

    我目前正在学习 Haskell 中的应用程序 如果我没记错的话 列表有两个不同的应用实例 List and ZipList 第二个被定义为包装列表值的新类型 这ZipList应用实例对我来说似乎更直观 这可能是一个愚蠢的问题 但有具体原因吗
  • 这个方法比 Math.random() 更快吗?

    我是一名初学者 目前已经开始开发一款使用粒子群优化算法的 Android 游戏 我现在正在尝试稍微优化我的代码 并且 for 循环中有相当多的 Math random 几乎一直在运行 所以我正在考虑一种方法来绕过并跳过所有 Math ran
  • kotlin 从数组中获取随机字符串

    刚接触 kotlin 有不少问题和解答 大部分是 Java 方面的 在遵循文档并针对大量 SO 进行验证之后问题和答案 https stackoverflow com questions 6726963 random string from
  • 最小化 MC 模拟期间存储的 cuRAND 状态数量

    我目前正在 CUDA 中编写蒙特卡罗模拟 因此 我需要生成lots使用随机数cuRAND图书馆 每个线程处理一个巨大的元素floatarray 示例中省略 并在每次内核调用时生成 1 或 2 个随机数 通常的方法 参见下面的示例 似乎是为每
  • ST monad 是如何工作的?

    我知道 ST monad 有点像 IO 的弟弟 而 IO 又是添加了状态 monadRealWorld魔法 我可以想象状态 也可以想象 RealWorld 以某种方式放入 IO 中 但每次我写一个类型签名ST the sST monad 的
  • 如何在Haskell中实现词法分析器和解析器

    我在这里得到了这段代码 它是用Haskell结构的命令式编程语言编写的程序 所以问题是 我如何为这种语言实现词法分析器和解析器 该程序被定义为一系列语句有 6 种类型 goto write stop if goto 和 int int n
  • C++ 中的随机数生成...第一个数字不是很随机

    我试图在 C 中获得 0 到 1 之间的统一随机数 而不使用 boost 我不想依赖图书馆 每当我开始我的计划时 我都会种子 srand 时间 NULL 然后我打印 8 个随机数 我用空行分隔程序的不同运行 Random number 0
  • C++ 概念与 Haskell 类型类有何不同?

    Concepts TS 中的 C 概念最近已合并到 GCC 主干中 概念允许人们通过要求类型满足概念的条件 例如 可比较 来约束通用代码 Haskell 有类型类 我对 Haskell 不太熟悉 概念和类型类如何相关 概念 由概念 TS 定
  • 迭代打印列表中的每个整数

    假设我有一个整数列表l 1 2 我想打印到stdout Doing print l产生 1 2 假设我想打印不带大括号的列表 map print l产生 No instance for Show IO arising from a use
  • 加密安全随机数生成器如何工作?

    我了解标准随机数生成器的工作原理 但在使用密码学时 随机数确实必须是随机的 我知道有一些仪器可以读取宇宙白噪声 http en wikipedia org wiki Hardware random number generator帮助生成安
  • 如何在haskell中用另一个字符串替换一个字符串

    我想用不同的字符串替换输入文件中的字符串 我正在寻找一种方法 但似乎我只能逐个字符地更改字符串 例如在我下面的代码中 replace String gt String replace replace x xs if x then y rep
  • 多个对象以某种方式相互干扰[原始版本]

    我有一个神经网络 NN 当应用于单个数据集时 它可以完美地工作 但是 如果我想在一组数据上运行神经网络 然后创建一个新的神经网络实例以在不同的数据集 甚至再次同一组数据 上运行 那么新实例将产生完全错误的预测 例如 对 XOR 模式进行训练
  • 在三角域内生成随机位置

    我想生成x and y具有均匀分布且受限于 xmin xmax and ymin ymax 点 x y 应位于三角形内 我该如何解决这样的问题 下面是一些在平面中的任意三角形上均匀生成点的代码 import random def point
  • 如何同时将透镜(或任何其他光学器件)视为吸气剂和设置剂?

    我正在尝试编写一个通用记录更新程序 它允许人们轻松更新记录中的字段existing记录 字段形状相似incoming记录 这是我到目前为止所拥有的 applyUpdater fields existing incoming let gett

随机推荐

  • 在haskell中剖析java类文件

    我今年早些时候刚刚开始学习 Haskell 语言 并且正在开发一个项目 该项目输入一个 java 类文件 即 FileName1 class 并剖析该文件以打印出以下内容 类文件定义的类名 类的方法数量 它们的名称和类型 我做了一些研究 发
  • C# 数据库应用程序并发

    我曾经用 C 编写过一个多用户应用程序 使用 SQL Server 2005 Express 作为后端 我有一个订单集合 为了使用此类 您需要实例化它并调用 Load CustomerCode 方法 以便使用指定客户的订单填充集合 我的问题
  • Vb.Net 属性语法

    我问过我的同事 甚至试图在互联网上查找这个问题 但我一直无法得到答案 有什么区别 Public Property Name As String and Public Property Name As String 在属性名称后面添加 有什么
  • 如何使这个简单的 OpenGL 代码(在“宽松”的 3.3 和 4.2 配置文件中工作)在严格的 3.2 和 4.2 核心配置文件中工作?

    我有一些 3D 代码 我注意到它们不会在严格的核心配置文件中呈现 但在 正常 未明确请求仅作为核心 配置文件上下文中正常 为了隔离这个问题 我编写了最简单的 OpenGL 程序 仅绘制一个三角形和一个矩形 我已经发布了OpenGL程序作为这
  • ASP.NET MVC - 简单面包屑(站点地图)

    我开发了一个 ASP NET MVC 2 应用程序 我想在每个页面中放置一个简单的面包屑 站点地图 如下所示 首页 gt 电影 gt 详情 它等于 URL http localhost home movies details http lo
  • 带有页眉、页脚和正文的简单 div

    我需要一个简单的div with header footer and body content The header and footer需要是fixed和heightdiv 的应该是250px or max 500px和它的width i
  • 从标准输入 C++ 读取数百万个整数的最快方法?

    我正在开发一个排序项目 现在主要瓶颈是读取数据 我的程序需要大约 20 秒才能对从 stdin 读取的 100 000 000 个整数进行排序cin and std ios sync with stdio false 但事实证明 其中 10
  • jquery 事件在附加后不起作用

    http jsfiddle net YsnhT 2 http jsfiddle net YsnhT 2 Jquery 事件在追加后不起作用 单击 保存 按钮后 我需要文本区域的值 span8 on click btn function va
  • 调用生成的 Serializer() 方法时收到 NoClassDefFoundError

    我得到了NoClassDefFoundError当尝试调用Foo serializer 上的方法 Serializable class 这是我的测试用例 Serializable data class Foo val data String
  • XMLHttpRequest 基本身份验证失败

    知道为什么吗XMLHttpRequest具有正确的凭据Pebble JS Framework http developer getpebble com 2 guides javascript guide html在 Android 上无法进
  • 铁路搜索表

    我正在创建一个跟踪用户和成就的应用程序 例如 xbox live 等 这些表通过连接表链接 我希望在我的索引上有一个搜索表单 让用户输入用户名 然后加载一个新页面 其中包含用户已获得的所有成就的列表 我不完全确定如何在索引上设置此搜索表单
  • 你能在Sqlite3(使用Django)中实现不区分大小写的“唯一”约束吗?

    假设我正在使用 Python 2 5 的内置默认 sqlite3 并且我有一个包含以下代码的 Django 模型类 class SomeEntity models Model some field models CharField max
  • 动态构建 SQL 查询(postgres 和 javascript)

    我有一个 javascript 函数需要返回产品列表 它使用 postgres 来检索产品列表 该函数传递一个categoryId和一个可选的typeId 所以我需要基于这些构建一个 SQL 查询 当然我可以做这样的事情 async fun
  • 具有多个 bert 输入的 SMOTE

    我正在使用 Keras 和 Bert HuggingFace 构建多类文本分类模型 但我有一个非常不平衡的数据集 我使用了 Sklearn 中的 SMOTE 来为欠平衡类生成额外的样本 我总共有 45 个 当我使用 Bert Tokeniz
  • 如何使用 matplotlib 制作“更完整”的轴箭头

    我有以下代码 from mpl toolkits axes grid axislines import SubplotZero from matplotlib transforms import BlendedGenericTransfor
  • 使用 Maven 时更改 Eclipse 中 Android R.java 的输出文件夹

    我有一个使用 maven android 插件的 android 项目设置 该插件遵循 Maven 输出文件夹的位置R java文件 即target generated sources r 但是 当在 Eclipse 中使用这个项目时 我无
  • Cppcheck 内联抑制不起作用

    示例代码 class Foo cppcheck suppress noExplicitConstructor Foo int foo Cpp检查调用 cppcheck exe enable all foo cpp Checking foo
  • 如何在 T-SQL 调试时查看表变量的值?

    在调试期间 我们能否在 SQL Server Management Studio SSMS 中查看表值变量中的值 行和单元格 如果是 怎么办 DECLARE v XML SELECT FROM
  • 本地使用 Cognito [离线]

    我有一种感觉 这是一个菜鸟问题 有没有办法在本地模拟 Cognito 用户池的使用 如此离线 我有一种感觉 在开发时诉诸 aws cognito 普通用户池是没有必要的 我现在知道无服务器有一个可以离线使用的插件 但没有找到用于 cogni
  • 在模拟中控制内存分配/GC?

    我在弄清楚如何减少运行在模拟中的内存使用和 GC 时间时遇到了一些麻烦State单子 目前我必须运行编译后的代码 RTS K100M为了避免堆栈空间溢出 GC 统计数据非常可怕 见下文 以下是相关代码片段 完整的工作 GHC 7 4 1 代