Skip to content

Commit

Permalink
Implement withBackend device placement function.
Browse files Browse the repository at this point in the history
`withBackend` explicitly demarcates code that should be run on a
different backend. It transfers inputs/results between backends
automatically.

Design info: feiwang3311#8 (comment)
  • Loading branch information
dan-zheng committed Oct 6, 2018
1 parent 1b1c2a8 commit cee7c9b
Showing 1 changed file with 55 additions and 2 deletions.
57 changes: 55 additions & 2 deletions src/main/scala/lantern/ad_lms_vector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,59 @@ trait TensorExp extends Dsl with Diff {
// in your DSL program.
var backend: Backend = new BackendNative

/**
* Transfer data between backends.
* @param from The current backend.
* @param to The new backend.
* @param data The data to transfer.
* @tparam T Type of the data.
*/
def transfer[T](from: Backend, to: Backend)(data: T) {
// TODO: Implement logic. It will involve `cudaMemcpy`.
(from, to) match {
case (cpu: BackendNative, gpu: BackendCudnn) => ???
case (gpu: BackendCudnn, cpu: BackendNative) => ???
case _ => ???
}
}

/**
* Call a function with given inputs, generating code for the specified backend.
* The inputs and result will be transferred between backends automatically.
* @param b The new backend.
* @param input The input to the function.
* @param f The function to call, whose code will be generated on the new backend.
* @tparam T The function input type.
* @tparam U The function output type.
*/
def withBackend[T, U](b: Backend, input: T)(f: T => U) = {
val originalBackend = backend

// Transfer input to the new backend.
// TODO: Consider using CPU-GPU shared memory?
transfer(originalBackend, b)(input)

// Change the backend (i.e. codegen target), then call `f`.
backend = b
val result = f(input)

// Transfer `result` to the old backend, then reset the backend.
transfer(originalBackend, b)(result)
backend = originalBackend
}

/**
* Call a function with given inputs, generating code for CPU.
* The inputs and result will be transferred between backends automatically.
*/
def withCPU[T, U](input: T)(f: T => U) = withBackend(new BackendNative, input)(f)

/**
* Call a function with given inputs, generating code for GPU (via `BackendCudnn`).
* The inputs and result will be transferred between backends automatically.
*/
def withGPU[T, U](input: T)(f: T => U) = withBackend(new BackendCudnn, input)(f)

class Tensor(val data: Rep[Array[Float]], val dimensions: NSeq[Int]) extends Serializable {

val MAX_DOUBLE = 1e10f // FIXME
Expand Down Expand Up @@ -578,8 +631,8 @@ trait TensorExp extends Dsl with Diff {

@virtualize
def sum2D(dim: Int) = {
assert (this.rank == 2, "Only deal with 2D tensor")
assert (dim == 0 || dim == 1, "dim must be in range of this.nbDims")
assert(this.rank == 2, "Only deal with 2D tensor")
assert(dim == 0 || dim == 1, "dim must be in range of this.nbDims")

if (dim == 0) ???
else {
Expand Down

0 comments on commit cee7c9b

Please sign in to comment.