How to understand the Matrix construction code?

26 views
Skip to first unread message

Ruizhe Zhao

unread,
Apr 8, 2019, 12:49:11 PM4/8/19
to Spatial Users
Hi all,

I am still working on the Spatial tutorials, and the lines that create Matrix in the GEMM tutorial are quite hard to understand.

val a = (0::m, 0::p){(i,j) => ((i + j * p) % 8).to[X] }

My question is: why the type of this value can be inferred as Matrix?

Thanks in advance for any help.

Best regards
Ruizhe

Ruizhe Zhao

unread,
Apr 8, 2019, 12:55:00 PM4/8/19
to Spatial Users
I tried to look at the inferred type through IntelliJ and it seems that this line of code will be expanded in some way caused by the @spatial annotation. Is that correct?

David Koeplinger

unread,
Apr 8, 2019, 2:45:11 PM4/8/19
to Spatial Users
The @spatial annotation actually doesn't do anything here.

This syntax is known as a matrix constructor. It was borrowed from another DSL called OptiML. You can interpret this as a two dimensional for loop which declares the contents of a matrix. The 0::n says to iterate over 0 to n-1 inclusive. The i and j are iterators over that two dimensional space.

The fact that it returns a Matrix is directly a result of it being a 2d space being iterated over. Similar constructors exist for 1 - 5d collections.

Ruizhe Zhao

unread,
Apr 11, 2019, 11:38:16 AM4/11/19
to Spatial Users
Hi David,

Thank you so much for your detailed reply. I can trace this syntax back in the OptiML paper.

Actually, I was more confused by the reason why such a concise expression could create a Matrix. I did a bit of research and realise that 0::n actually creates a Series, defined in argon. I will try to get a deeper understanding of the type system in the future.


David Koeplinger

unread,
Apr 11, 2019, 12:29:36 PM4/11/19
to Spatial Users
Ah yeah that's fair. In our implementation it's thanks to some Scala magic, but you could imagine a parser figuring out the same thing. Just for the sake of completeness I'll note where all this is coming from here.

You figured out the first one already, in Scala we have
implicit class IntOps(x: Int) {
 
def ::(y: Int): Series
}
allowing you to write something like 0::n. In general in Scala you can make implicit classes to add what look like infix functions to existing classes and primitive types.

The second part is
implicit class Tuple2Ops(bounds: Tuple2[Series,Series]) {
 
def apply[T](func: (Int,Int) => T): Matrix[T]
}

A tuple2 is created in scala just by putting parentheses around 2 things (e.g. (x,y)), and the apply is a special syntax for x(...).
The (Int,Int) => T is called a lambda function, and can be passed in Scala like you saw above. 

Those couple things together give the syntax you saw. It's one of the nice reasons for embedding DSLs in Scala.



Ruizhe Zhao

unread,
Apr 12, 2019, 4:34:18 AM4/12/19
to Spatial Users
Hi David,

Thank you for your in-depth analysis! I just viewed the concept of implicit class in Scala based on your post and now I'm clearer about how this DSL works :)

Best regards
Ruizhe
Reply all
Reply to author
Forward
0 new messages