zero strides

26 views
Skip to first unread message

lloda

unread,
Jul 3, 2020, 1:27:41 PM7/3/20
to blis-d...@googlegroups.com

The second call in the program below fails. Is this what's supposed to happen? I had assumed one could pass arbitrary strides.

I'm on Debian 10 in case it matters.

Regards

Daniel



8<------------------ program:

// $CXX -o blis-zero blis-zero.C -lblis -lm -lpthread

#include "blis.h"
#include <iostream>

using std::cout; using std::endl;

int main()
{
float a[4] = {1, 2, 3, 4};
float b[4] = {1, 2, 3, 4};
float c[4] = {1, 2, 3, 4};
float alpha = 1.;
float beta = 1.;

// 1*[1 2; 3 4]*[1 2; 3 4] + 1*[1 2; 3 4] -> [8 12; 18; 26]
bli_sgemm(BLIS_NO_TRANSPOSE, BLIS_NO_TRANSPOSE, 2, 2, 2, &alpha, a, 2, 1, b, 2, 1, &beta, c, 2, 1);
for (auto ci: c) cout << ci << endl;

// 1*[1 1; 1 1]*[1 2; 3 4] + 1*[1 2; 3 4] -> [5 8; 7 10]
bli_sgemm(BLIS_NO_TRANSPOSE, BLIS_NO_TRANSPOSE, 2, 2, 2, &alpha, a, 0, 0, b, 2, 1, &beta, c, 2, 1);
for (auto ci: c) cout << ci << endl;

return 0;
}

8<------------------ printout:

8
12
18
26

libblis: frame/base/check/bli_obj_check.c (line 106):
libblis: Encountered invalid stride/dimension combination.
libblis: Aborting.
Aborted

Devin Matthews

unread,
Jul 3, 2020, 1:32:00 PM7/3/20
to blis-d...@googlegroups.com
This is a discussion that I have had with the other BLIS developers for
some time. I am of your opinion that the strides should be completely
arbitrary (with the exception that elements of the output matrix/vector
must have unique addresses). However, the status quo is that "general
stride" means that, unlike BLAS/CBLAS, both strides may be non-unit.
They do still have to obey the restriction that rs,cs >= 1 and either cs
>= m*rs or rs >= n*cs.

It would help "our" cause if you could describe how such non-standard
strides are important in your use case?

Thanks,
Devin Matthews

lloda

unread,
Jul 3, 2020, 2:41:06 PM7/3/20
to blis-d...@googlegroups.com
(I wasn't subbed to the list, so I copied Devin's reply from the web interface. Apologies if it doesn't come out right.)

Most of the time the zero strides come from rank extending and tiling an array of lower rank. For example, if I need a big matrix of all the same x, it's a lot cheaper to just allocate space for a single x and set the strides to zero. Then the matrix can be as large as I want without using any additional space. Or if I need an matrix with repeated rows or columns, etc.

In some of these cases I might be able to reduce the gemm, etc. to something else. But when the tiling or slicing operations are mixed with other operations, at the point where I want to call gemm, I just have an array, I don't want to be concerned with how it was constructed. Either way it's well defined, so there's no reason to make the zero strides into special illegal cases (as long as one doesn't use them as write targets, as you say –- but even then, that's a separate check).

So I'm forced to check and convert arguments before calling BLIS, or I have to maintain an alternate implementation of gemm which is blind to the zero strides. It feels arbitrary, much like the other stride limitations in the original BLAS interface.

Regards

Daniel


> This is a discussion that I have had with the other BLIS developers for
> some time. I am of your opinion that the strides should be completely
> arbitrary (with the exception that elements of the output matrix/vector
> must have unique addresses). However, the status quo is that "general
> stride" means that, unlike BLAS/CBLAS, both strides may be non-unit.
> They do still have to obey the restriction that rs,cs >= 1 and either cs
> >= m*rs or rs >= n*cs.
>
> It would help "our" cause if you could describe how such non-standard
> strides are important in your use case?
>
> Thanks,
> Devin Matthews

>

Jeff Hammond

unread,
Jul 3, 2020, 2:41:29 PM7/3/20
to Devin Matthews, blis-discuss
The most obvious use case for stride-0 is to use a scalar instead of a vector, e.g. in AXPY [1]

MKL supports this but CUBLAS may not (it didn't in the past and I don't remember the last time I tested it [2]).  Netlib supports it [3] so I assume all implementations of CPU BLAS should support it.

Jeff

--
You received this message because you are subscribed to the Google Groups "blis-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blis-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blis-discuss/630f352e-752c-3444-190f-6189331d7f22%40smu.edu.


--

Devin Matthews

unread,
Jul 3, 2020, 2:53:08 PM7/3/20
to blis-d...@googlegroups.com
I commiserate with you. The situation may change in the future but for
now it is what it is.

Field: how hard would it be to add an environment variable that just
turns off the stride checks (use at your own risk disclaimer blah blah
blah)?

Devin

Field G. Van Zee

unread,
Jul 3, 2020, 4:49:39 PM7/3/20
to blis-d...@googlegroups.com
Officially allowing unconventional stride cases makes me nervous for
obvious reasons. (And you know how I feel about environment variables,
particularly when the information being conveyed pertains to how BLIS is
configured.)

My suggested short-term solution is to disable error checking at runtime:

bli_error_checking_level_set( BLIS_NO_ERROR_CHECKING );

and then proceed with the code as Daniel already has.

Field

Jeff Hammond

unread,
Jul 3, 2020, 4:54:38 PM7/3/20
to Field G. Van Zee, blis-discuss
What is a conventional stride?  How is stride-0 unconventional if BLAS supports it?

Jeff

--
You received this message because you are subscribed to the Google Groups "blis-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blis-discuss...@googlegroups.com.

Devin Matthews

unread,
Jul 3, 2020, 5:07:46 PM7/3/20
to blis-d...@googlegroups.com
BLAS supports zero strides for vectors, but not for matrices.

Devin

Field G. Van Zee

unread,
Jul 3, 2020, 5:10:07 PM7/3/20
to blis-d...@googlegroups.com
Yes, and Daniel's use case is that of gemm, not something like axpyv.

lloda

unread,
Jul 6, 2020, 3:47:44 PM7/6/20
to blis-d...@googlegroups.com

Thanks for all the replies.

I tried disabling the error checking (I was already checking shapes and such separately) and the gemm cases I tried all worked fine and gave the correct result. Zero on either stride or both, on either of the source arguments or both. Then I tried some non-zero strides that result in overlapping that the error checker also rejects (say cs = rs = 1), and those also gave the correct results.

The reasons not to support arbitrary strides aren't obvious to me, but of course I only come to BLIS as a user. I hope you reconsider at some point!

Regards

Daniel

Field G. Van Zee

unread,
Jul 6, 2020, 4:20:49 PM7/6/20
to blis-d...@googlegroups.com


On 7/6/20 2:47 PM, lloda wrote:
>
> Thanks for all the replies.
>
> I tried disabling the error checking (I was already checking shapes and such separately) and the gemm cases I tried all worked fine and gave the correct result. Zero on either stride or both, on either of the source arguments or both. Then I tried some non-zero strides that result in overlapping that the error checker also rejects (say cs = rs = 1), and those also gave the correct results.

Daniel,

I'm pleased (and a little surprised!) to hear that everything worked as
expected.

>
> The reasons not to support arbitrary strides aren't obvious to me, but of course I only come to BLIS as a user. I hope you reconsider at some point!

You're right to point out that it's not necessarily obvious to other
people! So let me explain.

I designed and wrote BLIS to operate under certain assumptions. One of
those assumptions was that matrices were conventionally stored in either
row-major (rs > 1, cs = 1), column-major (rs = 1, cs > 1), or "general"
format (rs > 1, cs > 1), with the third being like a slice of a 3D
tensor that is orthogonal to its unit dimension. I never contemplated
zero strides for anything beyond a trivial axpyv here or there. That's
not to say it doesn't work (as it appears to, based on your
experimentation) but rather that I never went out of my way to consider
it. I try to be meticulous and methodical about implementing and testing
BLIS, but again, only for the set of inputs I envisioned. If suddenly I
needed to test BLIS for inputs I *didn't* envision, my first instinctual
reaction is one of anxiety. :) So, that's what I meant by "makes me
nervous for obvious reasons."

I will certainly take note of other users asking for "official" zero
stride support. But until then, I would guess that BLIS encountering
zero strides is just as (if not more) likely to indicate a problem than
it is intentional behavior on the user's part. This is another reason
why I would prefer to keep the error checks in place by default while
still allowing more knowledgeable people such as yourself to consciously
disable them.

Please keep in touch, though. If you continue to use this functionality
over time, I may be open to adding a configure-time option that disables
*only* the stride checks. That way, you wouldn't need the runtime call
to disable error checking and you would still have the peace of mind of
having the other error checks enabled.

Field

lloda

unread,
Jul 7, 2020, 1:28:39 PM7/7/20
to blis-d...@googlegroups.com
> --
> You received this message because you are subscribed to the Google Groups "blis-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to blis-discuss...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/blis-discuss/04828aeb-b976-40bf-b9b7-63a5bc6666d1%40cs.utexas.edu.

Thanks Field, I understand a bit better now.

So far I've added a few tests for gemm and gemv using overlapping strides to my test suite, and I've found the results to be always correct. I'll keep adding tests and I'll post if I find anything of note.

If BLIS goes on to support arbitrary strides 'officially', a configure time option would be perfectly adequate, I think.

Regards

Daniel

Reply all
Reply to author
Forward
0 new messages