Hi,

first I wish to thank your for developing and maintaining the PyOpenCL library, 
which is a great tool. 
I'm using it for prototyping code for a research article.

I stumbled upon a problem past days,
Specifically, i was doing a cl.vector / scalar division, when i noticed in the 
array.py __div__ source code that the case scalar=1 is optimized.

Specifically, 

my test code is:

a = array([1,2,3,4]).astype(float32)
a_gpu = cl.array.to_device(queue,a)
b = float(1)         
c_gpu = a_gpu / b
print 'a_gpu',a_gpu.data,a_gpu
print 'b',b
print 'c_gpu',c_gpu.data,c_gpu  

at the end, the array c_gpu ends up being an alias to a_gpu, which was a very 
bad surprise.
I was expecting the '/' operator to allocate a new array and leave the 
arguments untouched. 

Actually the surprise was later in the code, when I modifed the contents of the 
c_gpu array (using a kernel) and noticed a_gpu modifed too.
This is a very nasty side effect. 


When inspecting array.py __div__ source code, i found out that these cases were 
purposely optimized out

  def __div__(self, other):
        """Divides an array by an array or a scalar, i.e. ``self / other``.
        """
        if isinstance(other, Array):
            result = self._new_like_me(
                    _get_common_dtype(self, other, self.queue))
            self._div(result, self, other)
        else:
            if other == 1:
                return self
            else:
                # create a new array for the result
                common_dtype = _get_common_dtype(self, other, self.queue)
                result = self._new_like_me(common_dtype)
                self._axpbz(result,
                        common_dtype.type(1/other), self, self.dtype.type(0))

        return result





Now, I'm questioning, this behaviour is intended as this? For me the 
consequence of the side-effect was disastrous, but maybe i'm missing something 
out.

Note, when working with pure numpy arrays, the results is always in a new copy. 
I'm using the regular __div__ operator, not the __idiv__ which I understand 
should be in-place modifier.
I noticed similar optimization for the neutral elements in pyopencl array 
__add__, __sub__ operators.
One might ask why am I dividing with '1' in the first place, but actually the 
'1' comes as a result of a previous calculation.


Thank you very much,
Istvan
_______________________________________________
PyOpenCL mailing list
[email protected]
http://lists.tiker.net/listinfo/pyopencl

Reply via email to