Zulip Chat Archive
Stream: lean4
Topic: Stack overflow with Array.mk
Ioannis Konstantoulas (Jul 23 2023 at 09:21):
Hello all;
I am testing Lean's capacity for memory allocation, and ran into the following problem (mwe follows):
def OnesList : List Nat := List.replicate (1000*1000*100) 1
def OnesArr := Array.mk OnesList
def One := OnesArr[1]?
-- main file
def main : IO Unit :=
IO.println s!"Hello, {One}!"
Compiling this with lake build
and running produces:
> lake build && time ( ./build/bin/performance )
[0/4] Building Performance
[1/4] Compiling Performance
[1/4] Building Main
[2/4] Compiling Main
[4/4] Linking performance
Stack overflow detected. Aborting.
[2] 168414 IOT instruction (core dumped) ( ./build/bin/performance; )
( ./build/bin/performance; ) 2.23s user 12.17s system 56% cpu 25.583 total
I expected an overflow for the List
type, but not when making the array; constructing the list and accessing some elements directly is fine:
lake build && time ( ./build/bin/performance )
[0/4] Building Performance
[1/4] Compiling Performance
[1/4] Building Main
[4/4] Linking performance
Hello, world!
Hello, (some 1)!
( ./build/bin/performance; ) 2.50s user 4.78s system 95% cpu 7.627 total
So I have a couple of questions:
-
Why does making the array from the list cause an overflow? Is this expected?
-
If we want to allocate and initiate large arrays, and producing them from lists overflows, what is the standard way to do it? Do we need to push or repeatedly self-append manually, or is there an optimized function?
Thanks for your time!
Ioannis Konstantoulas (Jul 23 2023 at 09:24):
Addendum: my lean version is Lean (version 4.0.0-nightly-2023-07-22, commit 544b704a2589, Release)
.
Daniil Kisel (Jul 23 2023 at 09:26):
For this specific case there is Array.mkArray
, which is equivalent to mk
+ List.replicate
but is implemented in C.
Scott Morrison (Jul 23 2023 at 09:26):
Also, your examples aren't that helpful, as you haven't shown us the code for both runs.
Scott Morrison (Jul 23 2023 at 09:27):
If you're trying to do large scale things, it seems strange to start with List
, rather than just directly working with Array
.
Ioannis Konstantoulas (Jul 23 2023 at 09:28):
Right, but since there does not seem to be any documentation for Array
pointing to the right constructors vs wrong constructors, I am just experimenting and asking here. Is there a better workflow? Also, I am not sure what you mean, the code is right there, there is no other code.
Ioannis Konstantoulas (Jul 23 2023 at 09:29):
Oh, I see, I forgot to paste the non-array part.
Ioannis Konstantoulas (Jul 23 2023 at 09:30):
Here is the code for the second compilation.
def OnesList : List Nat := List.replicate (1000*1000*100) 1
def One := OnesList[1]?
-- main file
def main : IO Unit :=
IO.println s!"Hello, {One}!"
Ioannis Konstantoulas (Jul 23 2023 at 09:35):
Daniil Kisel said:
For this specific case there is
Array.mkArray
, which is equivalent tomk
+List.replicate
but is implemented in C.
Thank you! Is there a corresponding function for List.iota
which creates an array of consecutive integers?
Daniil Kisel (Jul 23 2023 at 09:57):
Not that I know of.
Arthur Adjedj (Jul 23 2023 at 10:13):
Ioannis Konstantoulas said:
Daniil Kisel said:
For this specific case there is
Array.mkArray
, which is equivalent tomk
+List.replicate
but is implemented in C.Thank you! Is there a corresponding function for
List.iota
which creates an array of consecutive integers?
There isn't, but you can construct one yourself. Since the array will be modified in-place, you should still get pretty good performance out of it:
def IotaArr (size : Nat) := Id.run do
let mut arr := Array.mkEmpty size
for i in [0:size] do
arr := arr.push i
arr
def main : IO Unit :=
let arr := IotaArr 10000000
IO.println s!"Hello, {arr[10000]!}!"
Sebastian Ullrich (Jul 23 2023 at 10:40):
No need to pre-initialize the array, you can use mkEmpty
with a given capacity + push
Arthur Adjedj (Jul 23 2023 at 10:43):
Fixed :thumbs_up:
Last updated: Dec 20 2023 at 11:08 UTC