owi icon indicating copy to clipboard operation
owi copied to clipboard

symbolic sqrt is slow

Open epatrizio opened this issue 1 year ago • 8 comments

f32.sqrt and f64.sqrt instructions do not end. So, in symbolic tests, these instructions have been commented out.

https://github.com/OCamlPro/owi/blob/2ef083c191e8fa1da71ceb6b46f5d2dc19334841/test/sym/unop_f32.wat#L37

https://github.com/OCamlPro/owi/blob/2ef083c191e8fa1da71ceb6b46f5d2dc19334841/test/sym/unop_f64.wat#L37

epatrizio avatar Feb 13 '24 11:02 epatrizio

Small reproduction case:

(module
  (import "symbolic" "f32_symbol" (func $f32_symbol (result f32)))

  (func $start

    (f32.eq (f32.sqrt (call $f32_symbol)) (f32.const 0))
    (if (then unreachable))

  )

  (start $start)
)

~~Actually, this is hanging because encoding is raising Encoding.Solver.Unknown and we do not properly handle this in Symbolic_choice.~~

So two questions:

  • @filipeom, is it expected that Z3 can not handle sqrt ? After a quick search online, I believe we would have to use the non-linear solver or something like this ?
  • ~~@chambart, @krtab, could you have a look at how we could fix this in Symbolic_choice ? This is hopefully similar to ed033dfb7d665b941b19be3345834543a8c01231.~~

Also, on a related note, @filipeom, do you think we should change the type of Encoding.Solver.check (to a bool option for instance) to avoid using exceptions ?

redianthus avatar Feb 14 '24 16:02 redianthus

* @filipeom, is it expected that Z3 can not handle `sqrt` ? After a quick search online, I believe we would have to use the non-linear solver or something like this ?

Z3 should be able to handle the sqrt (but really slooowly, see https://github.com/formalsec/encoding/commit/92ae62526cfb1fc9bb7b872622271fad61493971)

Also, on a related note, @filipeom, do you think we should change the type of Encoding.Solver.check (to a bool option for instance) to avoid using exceptions ?

Yes, I agree this should be done :smiley: Either an option or a ADT like type satisfiabilty to be more expressive

Edit: I ran the example to reproduce and it gave-me this:

$ time owi sym test.wast
Trap: unreachable
Model:
  (model
    (symbol_0 (f32 -0.)))
Reached problem!
owi sym test.wast  17.68s user 0.10s system 99% cpu 17.809 total

filipeom avatar Feb 14 '24 17:02 filipeom

Also, using assert:

    (call $assert
      (f32.ne
        (f32.sqrt (local.get $f))
        (f32.const 0.0)))

Instead of:

    (f32.eq (f32.sqrt (call $f32_symbol)) (f32.const 0))
    (if (then unreachable))

Dropped execution time to ~10s. While, adding an assume, made it instantaneous. But not very interesting:

(module
  (import "symbolic" "f32_symbol" (func $f32_symbol (result f32)))
  (import "symbolic" "assume" (func $assume (param i32)))
  (import "symbolic" "assert" (func $assert (param i32)))
  (func $start
    (local $f f32)
    (local.set $f (call $f32_symbol))
    (call $assume
      (f32.eq
        (local.get $f)
        (f32.const 4.0)))
    (call $assert
      (f32.ne
        (f32.sqrt (local.get $f))
        (f32.const 2.0)))
  )

  (start $start)
)

filipeom avatar Feb 14 '24 18:02 filipeom

I cannot reproduce this either, neither on main nor on #170

krtab avatar Feb 19 '24 16:02 krtab

I can reproduce on main...

Not that it is looping indefinitely, but that it is very slow and we should try to fix it.

redianthus avatar Feb 19 '24 16:02 redianthus

I asked @silene (thanks again! :)) and this is because float arithmetic is implemented through bit-blasting. It is very slow because it requires generating a huge amount of variables. You can confirm this by:

  • using float64 which will be even worse;
  • printing the Z3 statistics (see #184) to see the number.

For some reason, it seems that using other numbers (e.g. 12 instead of 0, is a little bit faster).

If we still want to check this in our tests (and I'd like to), we should find numbers for which it is fast (and maybe combine this with the assert + f32.ne that @filipeom mentionned, if it makes things faster for some reason).

redianthus avatar Feb 21 '24 16:02 redianthus

For information, in the PR #194 mentioned above, float operations div and mul have been deactivated (they are very time-consuming - ~ 25 sec !) It's the same for float copysign, but it's less important.

epatrizio avatar Feb 26 '24 17:02 epatrizio