Numpy.einsum sometimes ignores the dtype argument

Suppose I have two arrays of type int8. I want to use einsum for them so that all calculations are done as int64, but I do not want to convert all arrays to int64. If I understand correctly, this is the dtype argument. But it does not seem to always work.

An example where it works as expected:

>>> A = np.array([[123, 45],[67,89]], dtype='int8') >>> np.einsum(A,[0,1],A,[0,1],[1]) ## => integer overflow array([-94, -38], dtype=int8) >>> np.einsum(A,[0,1],A,[0,1],[1], dtype='int64') ## => no overflow array([19618, 9946], dtype=int64) 

An example where it does not work properly:

 >>> A = np.array([[123, 45],[67,89]], dtype='int8') >>> np.einsum(A,[0,1],A,[1,2],[0,2]) ## => integer overflow array([[-32, 68], [124, -72]], dtype=int8) >>> np.einsum(A,[0,1],A,[1,2],[0,2], dtype='int64') ## => should not overflow, but it does array([[-32, 68], [124, -72]], dtype=int8) 

In these examples, I used python 3.6.4 for Windows with numpy 1.14.0

The same thing happens when I try to use other types of dtypes, for example float64, and even if I use casting = 'unsafe'.

Why is this happening, and how can I make it work?



UPDATE :
einsum optimize = True by default, at least in numpy 1.14.0. When using optimize = False, it works as expected (albeit much slower for large arrays):

 >>> A = np.array([[123, 45],[67,89]], dtype='int8') >>> np.einsum(A,[0,1],A,[1,2],[0,2]) ## => integer overflow array([[-32, 68], [124, -72]], dtype=int8) >>> np.einsum(A,[0,1],A,[1,2],[0,2], dtype='int64', optimize=False) array([[18144, 9540], [14204, 10936]], dtype=int64) 


From a brief look at einsum.py, it seems that with optimization = True, then it checks if it is better to use numpy.tensordot instead of implementing einsum. If this (which should be in my second example, since this is just regular matrix multiplication), then it uses tensordot, but does not pass the dtype argument to it. In fact, tensordot does not even have a dtype argument.


If this is correct, then the following question is required (what is probably worth his own post?):
How can I matrix-multiply two matrices of a certain type of dtype, say int8, in such a way that all calculations will be performed like, say, int64 or float64 (and therefore will not overflow / lose precision, if only int64 / float64 too), but without the need to first convert them to the desired type, and, in addition, the implementation of the operation itself does not have to convert the matrices as a whole, but only small parts each time (so that the memory required for the operation will not be much larger than the memory needed to store these matrices and result)?
Can this be done with performance comparable to numpy.dot?

+4
source share

Source: https://habr.com/ru/post/1276205/


All Articles