The Problem
I would like to multiply 2 sparse matrices efficiently under the Spark infrastructure in scalable manner, with the assumption that both matrices can fit into memory.
May Approach
At the beginning, for getting a comparable baseline, I took a dataframe with ~100,000 sparse vectors and performed trivial inner multiplication on one machine (by transforming to scipy csr matrix, spliting to batches and multiple all batches serially). The overall running time I got was 5 minutes.
Next, I implemented a fully map-reduce based algorithm over spark, using CoordinateMatrix as explained here and got a really bad performance - over 50 minutes (!) for the whole multiplication:
def coordinate_matrix_mul(mat_left, mat_right):
mat_left_cols = mat_left.entries.map(lambda entry: (entry.j, (entry.i, entry.value)))
mat_right_rows = mat_right.entries.map(lambda entry: (entry.i, (entry.j, entry.value)))
product_entries = mat_left_cols.join(mat_right_rows)\
.map(lambda pair: ((pair[1][0][0], pair[1][1][0]), pair[1][0][1]*pair[1][1][1]))\
.reduceByKey(lambda x,y: x+y)\
.map(lambda cell: MatrixEntry(cell[0][0], cell[0][1], cell[1]))
return CoordinateMatrix(product_entries)
My final approach was to take my first naive attempt (that didn't utilized spark with running time of 5 minutes), and parallelize the batches multiplication by the following steps:
- broadcast the left and right matrix to the workers.
- parallel the batches indicies in the form of [(from_row, to_row), ...] of the left matrix to rdd.
- map over the batches indicies and perform the multiplication simultaneously.
However I got the worst running time between all techniques above - over 60 minutes.
I tried changing the batche size, and checked if there is any lack of memory that causes swaping and threshing, but it wasn't the case.
Anyone have an idea what I am missing?
Thanks in advance.