Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent operations on variables from different contexts #1

Closed
mratsim opened this issue Apr 7, 2017 · 2 comments
Closed

Prevent operations on variables from different contexts #1

mratsim opened this issue Apr 7, 2017 · 2 comments
Labels

Comments

@mratsim
Copy link
Owner

mratsim commented Apr 7, 2017

This should not compile

let ctx1 = newContext[float32]()
let ctx2 = newContext[float32]()

let a = ctx1.variable(10)
let b = ctx2.variable(5)

let y = a + b #Should not compile
@mratsim
Copy link
Owner Author

mratsim commented Apr 7, 2017

What is possible today:

Context*[T] = object
  ## Tape / Wengert list. Contains the list of applied operations
  nodes: ref seq[Node[T]]
  context_id: int

And compare context_id for each operations I'm implementing
This is expensive especially in a loop (for Recurrent Neural Networks), repetitive and prone to mistakes (forget the if/then implementation on new operations)

The best way would be to have Nim typechecker check the Context at compile-time and avoid the costs at runtime (aka Dependant types).

One way to do this is by having a global counter, scoped to the module to avoid name conflict, and use this counter as a static[int] type.
This is pending nim-lang/Nim#3845:

type
  Node[T] = object

  Context*[T; I: static[int]] = object
    nodes: ref seq[Node[T]]

var CONTEXT_COUNTER {.compiletime.} = 0

proc ctx_handler(T: typedesc, I: static[int]): Context[T, I] {.noSideEffect.} =
  result.nodes = new seq[Node[T]]
  result.nodes[] = @[]

proc newContext*(T: typedesc): auto =
  inc CONTEXT_COUNTER
  return ctx_handler(T, CONTEXT_COUNTER)

let ctx = newContext(float32) # This line doesn't compile

The other way would be to have Context as a generic parameter to variable proc and Variable object.
That would require "generic generic parameters" https://github.com/nim-lang/Nim/issues/3856

type
  Node[T] = object

  Context*[T] = object
    nodes: ref seq[Node[T]]
  
  Variable*[T, CTX: Context] = object
    ## Wrapper for values
    tape: CTX # Generic generic would be lively to add the T constraint: https://github.com/nim-lang/Nim/issues/3856
    index: int
    value: T

proc newContext*[T]: Context[T] {.noSideEffect.} =
  ## Initialize a context (Tape / Wengert list)
  result.nodes = new seq[Node[T]]
  result.nodes[] = @[]

let ctx = newContext[float32]

proc push_nullary[T](t: Context[T]): int {.noSideEffect.} =
  ## Append a nullary operation to the context
  let len = t.len()
  t.push(
    Node[T](
      weights: [0.T, 0.T],
      deps: [len, len]
      )
    )
  return len

proc variable*[T](CTX: Context, value: T): Variable[T, CTX] {.noSideEffect.} =
  ## Wrap a variable to the context
  return Variable[T, CTX](
           tape: t,
           value: value,
           index: t.push_nullary()
           )

@mratsim mratsim changed the title Prevent operations on different contexts Prevent operations on variables from different contexts Apr 7, 2017
@mratsim
Copy link
Owner Author

mratsim commented Oct 25, 2017

Done by context being a ref object b8b3ff0

@mratsim mratsim closed this as completed Oct 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant