Repository: mahout
Updated Branches:
  refs/heads/master 84e90ed23 -> 034790cce


http://git-wip-us.apache.org/repos/asf/mahout/blob/034790cc/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/SrMatDnMatProdExpression.scala
----------------------------------------------------------------------
diff --git 
a/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/SrMatDnMatProdExpression.scala
 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/SrMatDnMatProdExpression.scala
new file mode 100644
index 0000000..24d2c7b
--- /dev/null
+++ 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/SrMatDnMatProdExpression.scala
@@ -0,0 +1,33 @@
+/**
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package org.apache.mahout.viennacl.opencl.javacpp
+
+import org.bytedeco.javacpp.Pointer
+import org.bytedeco.javacpp.annotation.{Name, Namespace, Platform, Properties}
+
+
+@Properties(inherit = Array(classOf[Context]),
+  value = Array(new Platform(
+    library = "jniViennaCL")
+  ))
+@Namespace("viennacl")
+@Name(Array("matrix_expression<const viennacl::compressed_matrix<double>, " +
+  "const viennacl::matrix_base<double>, " +
+  "viennacl::op_prod>"))
+class SrMatDnMatProdExpression extends Pointer {
+
+}

http://git-wip-us.apache.org/repos/asf/mahout/blob/034790cc/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VCLVector.scala
----------------------------------------------------------------------
diff --git 
a/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VCLVector.scala
 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VCLVector.scala
new file mode 100644
index 0000000..f0e3010
--- /dev/null
+++ 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VCLVector.scala
@@ -0,0 +1,133 @@
+/**
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package org.apache.mahout.viennacl.opencl.javacpp
+
+import org.bytedeco.javacpp._
+import org.bytedeco.javacpp.annotation._
+
+import scala.collection.mutable.ArrayBuffer
+
+
+@Properties(inherit = Array(classOf[Context]),
+  value = Array(new Platform(
+    library="jniViennaCL"
+  )))
+@Name(Array("viennacl::vector<double>"))
+final class VCLVector(defaultCtr: Boolean = true) extends VectorBase {
+
+  if (defaultCtr) allocate()
+
+  def this(){
+    this(false)
+    allocate()
+  }
+
+  def this(i: Int){
+    this(false)
+    allocate(i)
+  }
+
+  def this(size: Int, ctx: Context = new Context(Context.MAIN_MEMORY)) {
+    this(false)
+    allocate(size, ctx)
+  }
+
+  def this(@Const @ByRef ve: VecMultExpression) {
+    this(false)
+    allocate(ve)
+  }
+
+  def this(@Const @ByRef vmp: MatVecProdExpression) {
+    this(false)
+    allocate(vmp)
+  }
+
+//   conflicting with the next signature as MemHandle is a pointer and so is a 
DoublePointer..
+//   leave out for now.
+//
+//   def this(h: MemHandle , vec_size: Int, vec_start: Int = 0, vec_stride: 
Int = 1) {
+//      this(false)
+//      allocate(h, vec_size, vec_start, vec_stride)
+//    }
+
+  def this(ptr_to_mem: DoublePointer,
+           @Cast(Array("viennacl::memory_types"))mem_type : Int,
+           vec_size: Int,
+           start: Int = 0,
+           stride: Int = 1) {
+
+    this(false)
+    allocate(ptr_to_mem, mem_type, vec_size, start, stride)
+    ptrs += ptr_to_mem
+  }
+
+  def this(@Const @ByRef vc: VCLVector) {
+    this(false)
+    allocate(vc)
+  }
+  def this(@Const @ByRef vb: VectorBase) {
+    this(false)
+    allocate(vb)
+  }
+
+  @native protected def allocate()
+
+  @native protected def allocate(size: Int)
+
+  @native protected def allocate(size: Int, @ByVal ctx: Context)
+
+  @native protected def allocate(@Const @ByRef ve: VecMultExpression)
+
+  @native protected def allocate(@Const @ByRef ve: MatVecProdExpression)
+
+  @native protected def allocate(@Const @ByRef vb: VCLVector)
+
+  @native protected def allocate(@Const @ByRef vb: VectorBase)
+
+
+//  @native protected def allocate(h: MemHandle , vec_size: Int,
+//                                 vec_start: Int,
+//                                 vec_stride: Int)
+
+  @native protected def allocate(ptr_to_mem: DoublePointer,
+                                 
@Cast(Array("viennacl::memory_types"))mem_type : Int,
+                                 vec_size: Int,
+                                 start: Int,
+                                 stride: Int)
+
+  @Name(Array("viennacl::vector<double>::self_type"))
+  def selfType:VectorBase = this.asInstanceOf[VectorBase]
+
+
+  @native def switch_memory_context(@ByVal context: Context): Unit
+
+//  Swaps the handles of two vectors by swapping the OpenCL handles only, no 
data copy.
+//  @native def fast_swap(@ByVal other: VCLVector): VectorBase
+
+// add this operator in for tests many more can be added
+//  @Name(Array("operator*"))
+//  @native @ByPtr def *(i: Int): VectorMultExpression
+
+
+
+}
+
+object VCLVector {
+  Context.loadLib()
+}
+
+

http://git-wip-us.apache.org/repos/asf/mahout/blob/034790cc/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VecMultExpression.scala
----------------------------------------------------------------------
diff --git 
a/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VecMultExpression.scala
 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VecMultExpression.scala
new file mode 100644
index 0000000..1904151
--- /dev/null
+++ 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VecMultExpression.scala
@@ -0,0 +1,32 @@
+/**
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package org.apache.mahout.viennacl.opencl.javacpp
+
+import org.bytedeco.javacpp.Pointer
+import org.bytedeco.javacpp.annotation.{Name, Namespace, Platform, Properties}
+
+
+@Properties(inherit = Array(classOf[Context]),
+  value = Array(new Platform(
+    library = "jniViennaCL")
+  ))
+@Namespace("viennacl")
+@Name(Array("vector_expression<const viennacl::vector_base<double>," +
+  "const double, viennacl::op_mult >"))
+class VecMultExpression extends Pointer {
+
+}

http://git-wip-us.apache.org/repos/asf/mahout/blob/034790cc/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VectorBase.scala
----------------------------------------------------------------------
diff --git 
a/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VectorBase.scala
 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VectorBase.scala
new file mode 100644
index 0000000..43ae39d
--- /dev/null
+++ 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/javacpp/VectorBase.scala
@@ -0,0 +1,57 @@
+/**
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package org.apache.mahout.viennacl.opencl.javacpp
+
+import java.nio._
+
+import org.bytedeco.javacpp._
+import org.bytedeco.javacpp.annotation._
+
+import scala.collection.mutable.ArrayBuffer
+
+
+@Properties(inherit = Array(classOf[Context]),
+  value = Array(new Platform(
+    library="jniViennaCL"
+  )))
+@Name(Array("viennacl::vector_base<double>"))
+class VectorBase extends Pointer {
+
+  protected val ptrs = new ArrayBuffer[Pointer]()
+
+  override def deallocate(deallocate: Boolean): Unit = {
+    super.deallocate(deallocate)
+    ptrs.foreach(_.close())
+  }
+
+  // size of the vec elements
+  @native @Const def size(): Int
+
+  // size of the vec elements + padding
+  @native @Const def internal_size(): Int
+
+  // handle to the vec element buffer
+  @native @Const @ByRef def handle: MemHandle
+
+//  // add this operator in for tests many more can be added
+//  @Name(Array("operator* "))
+//  @native def *(i: Int): VectorMultExpression
+
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/mahout/blob/034790cc/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/package.scala
----------------------------------------------------------------------
diff --git 
a/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/package.scala 
b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/package.scala
new file mode 100644
index 0000000..8c3743a
--- /dev/null
+++ b/viennacl/src/main/scala/org/apache/mahout/viennacl/opencl/package.scala
@@ -0,0 +1,434 @@
+package org.apache.mahout.viennacl
+
+import java.nio._
+
+import org.apache.mahout.math._
+import scalabindings._
+import RLikeOps._
+import org.apache.mahout.math.backend.incore._
+import scala.collection.JavaConversions._
+import org.apache.mahout.viennacl.opencl.javacpp.{CompressedMatrix, Context, 
DenseRowMatrix, Functions, VCLVector}
+import org.apache.mahout.viennacl.opencl.javacpp.Context
+import org.bytedeco.javacpp.{DoublePointer, IntPointer}
+
+
+
+package object opencl {
+
+  type IntConvertor = Int => Int
+
+  def toVclDenseRM(src: Matrix, vclCtx: Context = new 
Context(Context.MAIN_MEMORY)): DenseRowMatrix = {
+    vclCtx.memoryType match {
+      case Context.MAIN_MEMORY ⇒
+        val vclMx = new DenseRowMatrix(
+          data = repackRowMajor(src, src.nrow, src.ncol),
+          nrow = src.nrow,
+          ncol = src.ncol,
+          ctx = vclCtx
+        )
+        vclMx
+      case _ ⇒
+        val vclMx = new DenseRowMatrix(src.nrow, src.ncol, vclCtx)
+        fastCopy(src, vclMx)
+        vclMx
+    }
+  }
+
+
+  /**
+    * Convert a dense row VCL matrix to mahout matrix.
+    *
+    * @param src
+    * @return
+    */
+  def fromVclDenseRM(src: DenseRowMatrix): Matrix = {
+    val nrowIntern = src.internalnrow
+    val ncolIntern = src.internalncol
+
+    // A technical debt here:
+
+    // We do double copying here, this is obviously suboptimal, but hopefully 
we'll compensate
+    // this with gains from running superlinear algorithms in VCL.
+    val dbuff = new DoublePointer(nrowIntern * ncolIntern)
+    Functions.fastCopy(src, dbuff)
+    var srcOffset = 0
+    val ncol = src.ncol
+    val rows = for (irow ← 0 until src.nrow) yield {
+
+      val rowvec = new Array[Double](ncol)
+      dbuff.position(srcOffset).get(rowvec)
+
+      srcOffset += ncolIntern
+      rowvec
+    }
+
+    // Always! use shallow = true to avoid yet another copying.
+    new DenseMatrix(rows.toArray, true)
+  }
+
+  def fastCopy(mxSrc: Matrix, dst: DenseRowMatrix) = {
+    val nrowIntern = dst.internalnrow
+    val ncolIntern = dst.internalncol
+
+    assert(nrowIntern >= mxSrc.nrow && ncolIntern >= mxSrc.ncol)
+
+    val rmajorData = repackRowMajor(mxSrc, nrowIntern, ncolIntern)
+    Functions.fastCopy(rmajorData, new 
DoublePointer(rmajorData).position(rmajorData.limit()), dst)
+
+    rmajorData.close()
+  }
+
+  private def repackRowMajor(mx: Matrix, nrowIntern: Int, ncolIntern: Int): 
DoublePointer = {
+
+    assert(mx.nrow <= nrowIntern && mx.ncol <= ncolIntern)
+
+    val dbuff = new DoublePointer(nrowIntern * ncolIntern)
+
+    mx match {
+      case dm: DenseMatrix ⇒
+        val valuesF = classOf[DenseMatrix].getDeclaredField("values")
+        valuesF.setAccessible(true)
+        val values = valuesF.get(dm).asInstanceOf[Array[Array[Double]]]
+        var dstOffset = 0
+        for (irow ← 0 until mx.nrow) {
+          val rowarr = values(irow)
+          dbuff.position(dstOffset).put(rowarr, 0, rowarr.size min ncolIntern)
+          dstOffset += ncolIntern
+        }
+        dbuff.position(0)
+      case _ ⇒
+        // Naive copying. Could be sped up for a DenseMatrix. TODO.
+        for (row ← mx) {
+          val dstOffset = row.index * ncolIntern
+          for (el ← row.nonZeroes) dbuff.put(dstOffset + el.index, el)
+        }
+    }
+
+    dbuff
+  }
+
+  /**
+    *
+    * @param mxSrc
+    * @param ctx
+    * @return
+    */
+  def toVclCmpMatrixAlt(mxSrc: Matrix, ctx: Context): CompressedMatrix = {
+
+    // use repackCSR(matrix, ctx) to convert all ints to unsigned ints if 
Context is Ocl
+    // val (jumpers, colIdcs, els) = repackCSRAlt(mxSrc)
+    val (jumpers, colIdcs, els) = repackCSR(mxSrc, ctx)
+
+    val compMx = new CompressedMatrix(mxSrc.nrow, mxSrc.ncol, 
els.capacity().toInt, ctx)
+    compMx.set(jumpers, colIdcs, els, mxSrc.nrow, mxSrc.ncol, 
els.capacity().toInt)
+    compMx
+  }
+
+  private def repackCSRAlt(mx: Matrix): (IntPointer, IntPointer, 
DoublePointer) = {
+    val nzCnt = mx.map(_.getNumNonZeroElements).sum
+    val jumpers = new IntPointer(mx.nrow + 1L)
+    val colIdcs = new IntPointer(nzCnt + 0L)
+    val els = new DoublePointer(nzCnt)
+    var posIdx = 0
+
+    var sortCols = false
+
+    // Row-wise loop. Rows may not necessarily come in order. But we have to 
have them in-order.
+    for (irow ← 0 until mx.nrow) {
+
+      val row = mx(irow, ::)
+      jumpers.put(irow.toLong, posIdx)
+
+      // Remember row start index in case we need to restart conversion of 
this row if out-of-order
+      // column index is detected
+      val posIdxStart = posIdx
+
+      // Retry loop: normally we are done in one pass thru it unless we need 
to re-run it because
+      // out-of-order column was detected.
+      var done = false
+      while (!done) {
+
+        // Is the sorting mode on?
+        if (sortCols) {
+
+          // Sorting of column indices is on. So do it.
+          row.nonZeroes()
+            // Need to convert to a strict collection out of iterator
+            .map(el ⇒ el.index → el.get)
+            // Sorting requires Sequence api
+            .toSeq
+            // Sort by column index
+            .sortBy(_._1)
+            // Flush to the CSR buffers.
+            .foreach { case (index, v) ⇒
+              colIdcs.put(posIdx.toLong, index)
+              els.put(posIdx.toLong, v)
+              posIdx += 1
+            }
+
+          // Never need to retry if we are already in the sorting mode.
+          done = true
+
+        } else {
+
+          // Try to run unsorted conversion here, switch lazily to sorted if 
out-of-order column is
+          // detected.
+          var lastCol = 0
+          val nzIter = row.nonZeroes().iterator()
+          var abortNonSorted = false
+
+          while (nzIter.hasNext && !abortNonSorted) {
+
+            val el = nzIter.next()
+            val index = el.index
+
+            if (index < lastCol) {
+
+              // Out of order detected: abort inner loop, reset posIdx and 
retry with sorting on.
+              abortNonSorted = true
+              sortCols = true
+              posIdx = posIdxStart
+
+            } else {
+
+              // Still in-order: save element and column, continue.
+              els.put(posIdx, el)
+              colIdcs.put(posIdx.toLong, index)
+              posIdx += 1
+
+              // Remember last column seen.
+              lastCol = index
+            }
+          } // inner non-sorted
+
+          // Do we need to re-run this row with sorting?
+          done = !abortNonSorted
+
+        } // if (sortCols)
+
+      } // while (!done) retry loop
+
+    } // row-wise loop
+
+    // Make sure Mahout matrix did not cheat on non-zero estimate.
+    assert(posIdx == nzCnt)
+
+    jumpers.put(mx.nrow.toLong, nzCnt)
+
+    (jumpers, colIdcs, els)
+  }
+
+  // same as repackCSRAlt except converts to jumpers, colIdcs to unsigned ints 
before setting
+  private def repackCSR(mx: Matrix, context: Context): (IntPointer, 
IntPointer, DoublePointer) = {
+    val nzCnt = mx.map(_.getNumNonZeroElements).sum
+    val jumpers = new IntPointer(mx.nrow + 1L)
+    val colIdcs = new IntPointer(nzCnt + 0L)
+    val els = new DoublePointer(nzCnt)
+    var posIdx = 0
+
+    var sortCols = false
+
+    def convertInt: IntConvertor = if(context.memoryType == 
Context.OPENCL_MEMORY) {
+      int2cl_uint
+    } else {
+      i: Int => i: Int
+    }
+
+    // Row-wise loop. Rows may not necessarily come in order. But we have to 
have them in-order.
+    for (irow ← 0 until mx.nrow) {
+
+      val row = mx(irow, ::)
+      jumpers.put(irow.toLong, posIdx)
+
+      // Remember row start index in case we need to restart conversion of 
this row if out-of-order
+      // column index is detected
+      val posIdxStart = posIdx
+
+      // Retry loop: normally we are done in one pass thru it unless we need 
to re-run it because
+      // out-of-order column was detected.
+      var done = false
+      while (!done) {
+
+        // Is the sorting mode on?
+        if (sortCols) {
+
+          // Sorting of column indices is on. So do it.
+          row.nonZeroes()
+            // Need to convert to a strict collection out of iterator
+            .map(el ⇒ el.index → el.get)
+            // Sorting requires Sequence api
+            .toIndexedSeq
+            // Sort by column index
+            .sortBy(_._1)
+            // Flush to the CSR buffers.
+            .foreach { case (index, v) ⇒
+            // convert to cl_uint if context is OCL
+            colIdcs.put(posIdx.toLong, convertInt(index))
+            els.put(posIdx.toLong, v)
+            posIdx += 1
+          }
+
+          // Never need to retry if we are already in the sorting mode.
+          done = true
+
+        } else {
+
+          // Try to run unsorted conversion here, switch lazily to sorted if 
out-of-order column is
+          // detected.
+          var lastCol = 0
+          val nzIter = row.nonZeroes().iterator()
+          var abortNonSorted = false
+
+          while (nzIter.hasNext && !abortNonSorted) {
+
+            val el = nzIter.next()
+            val index = el.index
+
+            if (index < lastCol) {
+
+              // Out of order detected: abort inner loop, reset posIdx and 
retry with sorting on.
+              abortNonSorted = true
+              sortCols = true
+              posIdx = posIdxStart
+
+            } else {
+
+              // Still in-order: save element and column, continue.
+              els.put(posIdx, el)
+              // convert to cl_uint if context is OCL
+              colIdcs.put(posIdx.toLong, convertInt(index))
+              posIdx += 1
+
+              // Remember last column seen.
+              lastCol = index
+            }
+          } // inner non-sorted
+
+          // Do we need to re-run this row with sorting?
+          done = !abortNonSorted
+
+        } // if (sortCols)
+
+      } // while (!done) retry loop
+
+    } // row-wise loop
+
+    // Make sure Mahout matrix did not cheat on non-zero estimate.
+    assert(posIdx == nzCnt)
+
+    // convert to cl_uint if context is OCL
+    jumpers.put(mx.nrow.toLong, convertInt(nzCnt))
+
+    (jumpers, colIdcs, els)
+  }
+
+
+
+  def fromVclCompressedMatrix(src: CompressedMatrix): Matrix = {
+    val m = src.size1
+    val n = src.size2
+    val NNz = src.nnz
+
+    val row_ptr_handle = src.handle1
+    val col_idx_handle = src.handle2
+    val element_handle = src.handle
+
+    val row_ptr = new IntPointer((m + 1).toLong)
+    val col_idx = new IntPointer(NNz.toLong)
+    val values = new DoublePointer(NNz.toLong)
+
+    Functions.memoryReadInt(row_ptr_handle, 0, (m + 1) * 4, row_ptr, false)
+    Functions.memoryReadInt(col_idx_handle, 0, NNz * 4, col_idx, false)
+    Functions.memoryReadDouble(element_handle, 0, NNz * 8, values, false)
+
+    val rowPtr = row_ptr.asBuffer()
+    val colIdx = col_idx.asBuffer()
+    val vals = values.asBuffer()
+
+    rowPtr.rewind()
+    colIdx.rewind()
+    vals.rewind()
+
+
+    val srMx = new SparseRowMatrix(m, n)
+
+    // read the values back into the matrix
+    var j = 0
+    // row wise, copy any non-zero elements from row(i-1,::)
+    for (i <- 1 to m) {
+      // for each nonzero element, set column col(idx(j) value to vals(j)
+      while (j < rowPtr.get(i)) {
+        srMx(i - 1, colIdx.get(j)) = vals.get(j)
+        j += 1
+      }
+    }
+    srMx
+  }
+
+  def toVclVec(vec: Vector, ctx: Context): VCLVector = {
+
+    vec match {
+      case vec: DenseVector => {
+        val valuesF = classOf[DenseVector].getDeclaredField("values")
+        valuesF.setAccessible(true)
+        val values = valuesF.get(vec).asInstanceOf[Array[Double]]
+        val el_ptr = new DoublePointer(values.length.toLong)
+        el_ptr.put(values, 0, values.length)
+
+        new VCLVector(el_ptr, ctx.memoryType, values.length)
+      }
+
+      case vec: SequentialAccessSparseVector => {
+        val it = vec.iterateNonZero
+        val size = vec.size()
+        val el_ptr = new DoublePointer(size.toLong)
+        while (it.hasNext) {
+          val el: Vector.Element = it.next
+          el_ptr.put(el.index, el.get())
+        }
+        new VCLVector(el_ptr, ctx.memoryType, size)
+      }
+
+      case vec: RandomAccessSparseVector => {
+        val it = vec.iterateNonZero
+        val size = vec.size()
+        val el_ptr = new DoublePointer(size.toLong)
+        while (it.hasNext) {
+          val el: Vector.Element = it.next
+          el_ptr.put(el.index, el.get())
+        }
+        new VCLVector(el_ptr, ctx.memoryType, size)
+      }
+      case _ => throw new IllegalArgumentException("Vector sub-type not 
supported.")
+    }
+
+  }
+
+  def fromVClVec(vclVec: VCLVector): Vector = {
+    val size = vclVec.size
+    val element_handle = vclVec.handle
+    val ele_ptr = new DoublePointer(size)
+    Functions.memoryReadDouble(element_handle, 0, size * 8, ele_ptr, false)
+
+    // for now just assume its dense since we only have one flavor of
+    // VCLVector
+    val mVec = new DenseVector(size)
+    for (i <- 0 until size) {
+      mVec.setQuick(i, ele_ptr.get(i + 0L))
+    }
+
+    mVec
+  }
+
+
+  // TODO: Fix this?  cl_uint must be an unsigned int per each machine's 
representation of such.
+  // this is currently not working anyways.
+  // cl_uint is needed for OpenCl sparse Buffers
+  // per 
https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/scalarDataTypes.html
+  // it is simply an unsigned int, so strip the sign.
+  def int2cl_uint(i: Int): Int = {
+    ((i >>> 1) << 1) + (i & 1)
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/mahout/blob/034790cc/viennacl/src/test/scala/org/apache/mahout/viennacl/opencl/ViennaCLSuiteVCL.scala
----------------------------------------------------------------------
diff --git 
a/viennacl/src/test/scala/org/apache/mahout/viennacl/opencl/ViennaCLSuiteVCL.scala
 
b/viennacl/src/test/scala/org/apache/mahout/viennacl/opencl/ViennaCLSuiteVCL.scala
new file mode 100644
index 0000000..c433534
--- /dev/null
+++ 
b/viennacl/src/test/scala/org/apache/mahout/viennacl/opencl/ViennaCLSuiteVCL.scala
@@ -0,0 +1,427 @@
+/**
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  * http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package org.apache.mahout.opencl.viennacl
+
+import org.apache.mahout.math._
+import org.apache.mahout.math.scalabindings.RLikeOps._
+import org.apache.mahout.viennacl.opencl.javacpp.CompressedMatrix
+import org.apache.mahout.viennacl.opencl._
+import org.apache.mahout.viennacl.opencl.javacpp.Functions._
+import org.apache.mahout.viennacl.opencl.javacpp.LinalgFunctions._
+import org.apache.mahout.viennacl.opencl.javacpp.{Context, LinalgFunctions, 
VCLVector, _}
+import org.bytedeco.javacpp.DoublePointer
+import org.scalatest.{FunSuite, Matchers}
+
+import scala.util.Random
+
+class ViennaCLSuiteVCL extends FunSuite with Matchers {
+
+  test("row-major viennacl::matrix") {
+
+    // Just to make sure the javacpp library is loaded:
+    Context.loadLib()
+
+    val m = 20
+    val n = 30
+    val data = new DoublePointer(m * n)
+    val buff = data.asBuffer()
+    // Fill with some noise
+    while (buff.remaining() > 0) buff.put(Random.nextDouble())
+
+    // Create row-major matrix with OpenCL
+    val openClCtx = new Context(Context.OPENCL_MEMORY)
+    val hostClCtx = new Context(Context.MAIN_MEMORY)
+    val oclMx = new DenseRowMatrix(m, n, openClCtx)
+    val cpuMx = new DenseRowMatrix(data = data, nrow = m, ncol = n, hostClCtx)
+
+    oclMx.memoryDomain shouldBe Context.OPENCL_MEMORY
+
+    // Apparently, this doesn't really switch any contexts? any how, 
uncommenting this causes
+    // subsequent out-of-resources OCL error for me in other tests. Perhaps we 
shouldnt' really
+    // do cross-memory-domain assigns?
+
+    //    oclMx := cpuMx
+
+    // Did it change memory domain? that may explain the OCL resource leak.
+    info(s"OCL matrix memory domain after assgn=${oclMx.memoryDomain}")
+    oclMx.memoryDomain shouldBe Context.OPENCL_MEMORY
+
+
+    // And free.
+    cpuMx.close()
+    oclMx.close()
+
+  }
+
+  test("dense vcl mmul with fast_copy") {
+
+    import LinalgFunctions._
+
+    val vclCtx = new Context(Context.OPENCL_MEMORY)
+
+    val m = 20
+    val n = 30
+    val s = 40
+
+    val r = new Random(1234)
+
+    // Dense row-wise
+    val mxA = new DenseMatrix(m, s)
+    val mxB = new DenseMatrix(s, n)
+
+    // add some data
+    mxA := { (_, _, _) => r.nextDouble() }
+    mxB := { (_, _, _) => r.nextDouble() }
+
+    // time Mahout MMul
+    // mxC = mxA %*% mxB via Mahout MMul
+    val mxCControl = mxA %*% mxB
+
+    val vclA = toVclDenseRM(mxA, vclCtx)
+    val vclB = toVclDenseRM(mxB, vclCtx)
+
+    val vclC = new DenseRowMatrix(prod(vclA, vclB))
+
+    val mxC = fromVclDenseRM(vclC)
+
+    vclA.close()
+    vclB.close()
+    vclC.close()
+
+    // So did we compute it correctly?
+    (mxC - mxA %*% mxB).norm / m / n should be < 1e-16
+
+    vclCtx.deallocate()
+    vclCtx.close()
+
+  }
+
+  test("mmul microbenchmark") {
+    val oclCtx = new Context(Context.OPENCL_MEMORY)
+    val memCtx = new Context(Context.MAIN_MEMORY)
+
+    val m = 3000
+    val n = 3000
+    val s = 1000
+
+    val r = new Random(1234)
+
+    // Dense row-wise
+    val mxA = new DenseMatrix(m, s)
+    val mxB = new DenseMatrix(s, n)
+
+    // add some data
+    mxA := { (_, _, _) => r.nextDouble() }
+    mxB := { (_, _, _) => r.nextDouble() }
+
+    var ms = System.currentTimeMillis()
+    mxA %*% mxB
+    ms = System.currentTimeMillis() - ms
+    info(s"Mahout multiplication time: $ms ms.")
+
+    import LinalgFunctions._
+
+    // openCL time, including copying:
+    {
+      ms = System.currentTimeMillis()
+      val oclA = toVclDenseRM(mxA, oclCtx)
+      val oclB = toVclDenseRM(mxB, oclCtx)
+      val oclC = new DenseRowMatrix(prod(oclA, oclB))
+      val mxC = fromVclDenseRM(oclC)
+      ms = System.currentTimeMillis() - ms
+      info(s"ViennaCL/OpenCL multiplication time: $ms ms.")
+
+      oclA.close()
+      oclB.close()
+      oclC.close()
+    }
+
+    // openMP/cpu time, including copying:
+    {
+      ms = System.currentTimeMillis()
+      val ompA = toVclDenseRM(mxA, memCtx)
+      val ompB = toVclDenseRM(mxB, memCtx)
+      val ompC = new DenseRowMatrix(prod(ompA, ompB))
+      val mxC = fromVclDenseRM(ompC)
+      ms = System.currentTimeMillis() - ms
+      info(s"ViennaCL/cpu/OpenMP multiplication time: $ms ms.")
+
+      ompA.close()
+      ompB.close()
+      ompC.close()
+    }
+    oclCtx.deallocate()
+    oclCtx.close()
+
+
+  }
+
+  test("trans") {
+
+    val oclCtx = new Context(Context.OPENCL_MEMORY)
+    val ompCtx = new Context(Context.MAIN_MEMORY)
+
+
+    val m = 20
+    val n = 30
+
+    val r = new Random(1234)
+
+    // Dense row-wise
+    val mxA = new DenseMatrix(m, n)
+
+    // add some data
+    mxA := { (_, _, _) => r.nextDouble() }
+
+    // Test transposition in OpenCL
+    {
+      val oclA = toVclDenseRM(src = mxA, oclCtx)
+      val oclAt = new DenseRowMatrix(trans(oclA))
+
+      val mxAt = fromVclDenseRM(oclAt)
+      oclA.close()
+      oclAt.close()
+
+      (mxAt - mxA.t).norm / m / n should be < 1e-16
+    }
+
+    // Test transposition in OpenMP
+    {
+      val ompA = toVclDenseRM(src = mxA, ompCtx)
+      val ompAt = new DenseRowMatrix(trans(ompA))
+
+      val mxAt = fromVclDenseRM(ompAt)
+      ompA.close()
+      ompAt.close()
+
+      (mxAt - mxA.t).norm / m / n should be < 1e-16
+    }
+    oclCtx.deallocate()
+    oclCtx.close()
+
+
+  }
+
+  test("sparse mmul microbenchmark") {
+
+    val oclCtx = new Context(Context.OPENCL_MEMORY)
+    val ompCtx = new Context(Context.MAIN_MEMORY)
+
+
+    val m = 3000
+    val n = 3000
+    val s = 1000
+
+    val r = new Random(1234)
+
+    // sparse row-wise
+    val mxA = new SparseRowMatrix(m, s, false)
+    val mxB = new SparseRowMatrix(s, n, true)
+
+    // add some sparse data with a 20% threshold
+    mxA := { (_, _, v) => if (r.nextDouble() < .20) r.nextDouble() else v }
+    mxB := { (_, _, v) => if (r.nextDouble() < .20) r.nextDouble() else v }
+
+    var ms = System.currentTimeMillis()
+    val mxC = mxA %*% mxB
+    ms = System.currentTimeMillis() - ms
+    info(s"Mahout Sparse multiplication time: $ms ms.")
+
+//     Test multiplication in OpenCL
+    {
+
+      ms = System.currentTimeMillis()
+      val oclA = toVclCmpMatrixAlt(mxA, oclCtx)
+      val oclB = toVclCmpMatrixAlt(mxB, oclCtx)
+
+      val oclC = new CompressedMatrix(prod(oclA, oclB))
+      ms = System.currentTimeMillis() - ms
+      info(s"ViennaCL/OpenCL Sparse multiplication time: $ms ms.")
+
+      val oclMxC = fromVclCompressedMatrix(oclC)
+      val ompMxC = fromVclCompressedMatrix(oclC)
+      (mxC - oclMxC).norm / mxC.nrow / mxC.ncol should be < 1e-16
+
+      oclA.close()
+      oclB.close()
+      oclC.close()
+    }
+
+    // Test multiplication in OpenMP
+    {
+      ms = System.currentTimeMillis()
+      //      val ompA = toVclCompressedMatrix(src = mxA, ompCtx)
+      //      val ompB = toVclCompressedMatrix(src = mxB, ompCtx)
+
+      val ompA = toVclCmpMatrixAlt(mxA, ompCtx)
+      val ompB = toVclCmpMatrixAlt(mxB, ompCtx)
+
+      val ompC = new CompressedMatrix(prod(ompA, ompB))
+
+      ms = System.currentTimeMillis() - ms
+      info(s"ViennaCL/cpu/OpenMP Sparse multiplication time: $ms ms.")
+
+      val ompMxC = fromVclCompressedMatrix(ompC)
+      (mxC - ompMxC).norm / mxC.nrow / mxC.ncol should be < 1e-16
+
+      ompA.close()
+      ompB.close()
+      ompC.close()
+
+    }
+    oclCtx.deallocate()
+    oclCtx.close()
+
+  }
+
+  test("VCL Dense Matrix %*% Dense vector") {
+
+    val oclCtx = new Context(Context.OPENCL_MEMORY)
+    val ompCtx = new Context(Context.MAIN_MEMORY)
+
+
+    val m = 30
+    val s = 10
+
+    val r = new Random(1234)
+
+    // Dense row-wise
+    val mxA = new DenseMatrix(m, s)
+    val dvecB = new DenseVector(s)
+
+    // add some random data
+    mxA := { (_,_,_) => r.nextDouble() }
+    dvecB := { (_,_) => r.nextDouble() }
+
+    //test in matrix %*% vec
+    var ms = System.currentTimeMillis()
+    val mDvecC = mxA %*% dvecB
+    ms = System.currentTimeMillis() - ms
+    info(s"Mahout dense matrix %*% dense vector multiplication time: $ms ms.")
+
+
+    /* TODO: CL_OUT_OF_RESOURCES error thrown when trying to read data out of 
OpenCl GPU Vectors  */
+    //Test multiplication in OpenCL
+//      {
+//
+//        ms = System.currentTimeMillis()
+//        val oclA = toVclDenseRM(mxA, oclCtx)
+//        val oclVecB = toVclVec(dvecB, oclCtx)
+//
+//        val oclVecC = new VCLVector(prod(oclA, oclVecB))
+//        val oclDvecC = fromVClVec(oclVecC)
+////
+////        ms = System.currentTimeMillis() - ms
+////        info(s"ViennaCL/OpenCL dense matrix %*% dense vector 
multiplication time: $ms ms.")
+////        (oclDvecC.toColMatrix - mDvecC.toColMatrix).norm / s  should be < 
1e-16
+//
+//        oclA.close()
+//        oclVecB.close()
+//        oclVecC.close()
+//      }
+
+    //Test multiplication in OpenMP
+      {
+
+        ms = System.currentTimeMillis()
+        val ompMxA = toVclDenseRM(mxA, ompCtx)
+        val ompVecB = toVclVec(dvecB, ompCtx)
+
+        val ompVecC = new VCLVector(prod(ompMxA, ompVecB))
+        val ompDvecC = fromVClVec(ompVecC)
+
+        ms = System.currentTimeMillis() - ms
+        info(s"ViennaCL/cpu/OpenMP dense matrix %*% dense vector 
multiplication time: $ms ms.")
+        (ompDvecC.toColMatrix - mDvecC.toColMatrix).norm / s  should be < 1e-16
+
+        ompMxA.close()
+        ompVecB.close()
+        ompVecC.close()
+      }
+
+      oclCtx.deallocate()
+      oclCtx.close()
+
+
+  }
+
+
+  test("Sparse %*% Dense mmul microbenchmark") {
+    val oclCtx = new Context(Context.OPENCL_MEMORY)
+    val memCtx = new Context(Context.MAIN_MEMORY)
+
+    val m = 3000
+    val n = 3000
+    val s = 1000
+
+    val r = new Random(1234)
+
+    // Dense row-wise
+    val mxSr = new SparseMatrix(m, s)
+    val mxDn = new DenseMatrix(s, n)
+
+    // add some data
+    mxSr := { (_, _, v) => if (r.nextDouble() < .20) r.nextDouble() else v }
+    mxDn := { (_, _, _) => r.nextDouble() }
+
+    var ms = System.currentTimeMillis()
+    mxSr %*% mxDn
+    ms = System.currentTimeMillis() - ms
+    info(s"Mahout multiplication time: $ms ms.")
+
+    import LinalgFunctions._
+
+    // For now, since our dense matrix is fully dense lets just assume that 
our result is dense.
+    // openCL time, including copying:
+    {
+      ms = System.currentTimeMillis()
+      val oclA = toVclCmpMatrixAlt(mxSr, oclCtx)
+      val oclB = toVclDenseRM(mxDn, oclCtx)
+      val oclC = new DenseRowMatrix(prod(oclA, oclB))
+      val mxC = fromVclDenseRM(oclC)
+      ms = System.currentTimeMillis() - ms
+      info(s"ViennaCL/OpenCL multiplication time: $ms ms.")
+
+      oclA.close()
+      oclB.close()
+      oclC.close()
+    }
+
+    // openMP/cpu time, including copying:
+    {
+      ms = System.currentTimeMillis()
+      val ompA = toVclCmpMatrixAlt(mxSr, memCtx)
+      val ompB = toVclDenseRM(mxDn, memCtx)
+      val ompC = new DenseRowMatrix(prod(ompA, ompB))
+      val mxC = fromVclDenseRM(ompC)
+      ms = System.currentTimeMillis() - ms
+      info(s"ViennaCL/cpu/OpenMP multiplication time: $ms ms.")
+
+      ompA.close()
+      ompB.close()
+      ompC.close()
+    }
+
+    oclCtx.deallocate()
+    oclCtx.close()
+
+
+  }
+
+
+
+}

Reply via email to