Утечка пространства происходит в одном из моих личных проектов. Но я не хочу, чтобы кто-то решал это в моем проекте. Я хочу это понять.Утечка пространства с рекурсивным списком zipWith
Я воспроизведен мое место утечки, делая этот алгоритм:
U представляет собой последовательность определяется по формуле:
- и (0) = 1
- и (1) = 2
- и (2) = 1
- и (4) = 3
- ...
- и (19) = 11
после этого, и определена: и (п) = и (п-5) + и (п-10) - и (п-15)
Легко реализовать в Haskell правильно?
import System.Environment (getArgs)
u = [1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11]
++ zipWith3 go u' u'' u'''
where u' = drop 15 u
u'' = drop 10 u
u''' = drop 5 u
go a b c = a + b - c
main = do
args <- getArgs
let n = read $ args !! 0
putStrLn $ show $ u !! n
К сожалению, это пространство утечки:
$ time ./algo 9999999
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
1.17user 0.19system 0:01.37elapsed 100%CPU (0avgtext+0avgdata 865124maxresident)k
0inputs+0outputs (0major+215695minor)pagefaults 0swaps
Похоже Haskell кэширование весь список, в котором, как я хочу, чтобы кэшировать только 20 последних элементов.
Например, вот моя реализация в C:
#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv)
{
size_t cursor;
int64_t buffer[20] = {1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11};
int n = atoi(argv[1]);
for (cursor = 20; cursor <= n; cursor++) {
buffer[cursor%20] = buffer[(cursor+20-5)%20] + buffer[(cursor+20-10)%20] - buffer[(cursor+20-15)%20];
}
printf("%d\n", buffer[n%20]);
return 0;
}
$ ./a.out 9999999
5000001
Моя реализация C использует O (N) времени и O (1) пространство. Но похоже, что реализация haskell использует O (n) пространство.
Почему Haskell способен вычислить его для fibonnacci, но не для моей составленной последовательности? Что я сделал не так? Как реализовать этот алгоритм в Haskell?
Вы скомпилировались с '-O2'? Кроме того, поскольку это значения верхнего уровня, GHC любит поддерживать его еще больше. Попробуйте определить его в 'where' в' main'. – bheklilr
с/без '-O2', верхний уровень/в закрытии main, в четырех случаях он ничего не меняет :( –