J语言中Memoization(M.)缓存表受限致程序重复计算变慢
J语言
M.缓存失效的解决办法 问题原因
J内置的M. memoization操作符缓存容量固定且无法由用户调整(从测试情况看默认容量为32)。当计算的参数数量超过这个阈值后,旧的缓存条目会被覆盖,导致后续需要重复计算已处理过的参数,缓存不仅没起到加速作用,还额外增加了管理开销,最终拖慢程序。
替代方案:手动实现缓存
既然内置缓存受限,我们可以自己维护缓存结构,完全控制缓存的存储逻辑,避免容量限制问题。以下是两种可行的实现方式:
1. 数组缓存(适合连续数字场景)
如果处理的是连续的数字序列,用数组作为缓存最节省空间且访问高效:
collatz =: (%&2)`(1+3&*)@.(2&|) cache =: 0:` NB. 缓存数组:索引对应数字,值对应步数,0表示未计算 countchain =: 3 : 0 NB. 扩展缓存到足够长度,避免索引越界 if. y > #cache do. cache =. cache , (y - #cache) $ 0 end. NB. 缓存命中直接返回 if. v =. cache {~ y do. v return. end. echo 'xx ' , ": y if. 1=y do. res =. 1 else. res =. 1 + countchain collatz y end. cache =. cache (y)} res NB. 将结果存入缓存 res )
2. 字典缓存(适合稀疏数字场景)
如果处理的数字不连续,用字典存储缓存更节省空间:
collatz =: (%&2)`(1+3&*)@.(2&|) cache =: (0 : 0) '' NB. 初始化空字典,键为数字,值为步数 countchain =: 3 : 0 NB. 缓存命中直接返回 if. y e. keys cache do. cache { y return. end. echo 'xx ' , ": y if. 1=y do. res =. 1 else. res =. 1 + countchain collatz y end. cache =. cache , (y;:res) NB. 将结果存入字典 res )
这两种手动缓存方式完全由开发者控制缓存的生命周期和容量,不会出现M.的缓存溢出覆盖问题,能有效避免重复计算,大幅提升长序列计算的效率。
内容的提问来源于stack exchange,提问作者Abang F.
相关产品推荐
相关产品推荐

