Skip to content

lax.cond, vmap and data dependent while loops may cause non-termination #2947

Description

@lumip

We recently ran into a situation quite similar to the following (simplified) code:

import jax

def positive_branch(x):
    # this function does not terminate for negative values
    def body(x):
        return x * 0.1

    return jax.lax.while_loop(lambda y: (y <= 0) | (y > 1e-6), body, x)

def negative_branch(x):
    # this function always terminates
    def body(x):
        return x * 0.1

    return jax.lax.while_loop(lambda y: y < -1e-6, body, x)

def branching_fn(x):
    return jax.lax.cond(x >= 0, x, positive_branch, x, negative_branch)

x = jax.random.normal(jax.random.PRNGKey(0), shape=(10,))

branching_fns = jax.vmap(branching_fn)
y = branching_fns(x)

print(y)

So in essence, we have a a while loop that only terminates if the condition that leads the branch it resides in to be executed is true. In classical sequential code this is not a problem, however, in this particular example, it results in non-termination.

What seems to be happening is that despite conditional branching using jax.lax.cond, both branches are executed (we suspect that jax.lax.cond in this case performs some kind of result multiplexing/selection instead of actual conditional executing).

What's a bit puzzling about this is that this does not occur when not using jax.vmap:

  • execution on a single data point does not exhibit the problem
  • jax.lax.map does not exhibit the problem

A fix in this example is to include the branching condition in the loops conditions to ensure they always terminate - but it might be worthwhile to think about how to fix this in the underlying implementation.. so can you maybe shed some light on what is causing this and whether it could be addressed? At least I think this should be documented somewhere (maybe on the sharp bits page). Also, what exactly is the difference between map and vmap in terms of performance/parallelization?

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions