diku-dk / futhark

:boom::computer::boom: A data-parallel functional programming language
http://futhark-lang.org
ISC License
2.37k stars 164 forks source link

Futhark-pyopencl crashes after it finishes compiling on Windows #165

Closed mrakgr closed 8 years ago

mrakgr commented 8 years ago
C:\futhark\examples>futhark-pyopencl --module blur.fut

C:\futhark\examples>      0 [main] us 0 init_cheap: VirtualAlloc pointer is null, Win32 error 487
AllocationBase 0x0, BaseAddress 0x60E90000, RegionSize 0x3E0000, State 0x10000
C:\msys+7za+wget+svn+git+mercurial+cvs-rev13\msys\bin\chmod.exe: *** Couldn't reserve space for cygwin's heap, Win32 error 0

I do not even have Cygwin installed, so I am not sure what exactly is going on here.

Actually, scratch that. It is not the backend that is crashing, but chmod itself on my computer. It throws the above error as soon as I run it. I am not too familiar with Linux, but depending on what it does, maybe chmod does not need to be run on Windows? Wiki says all it does is change access flags.

Is there a step after it? The chmod call might be blocking it.

athas commented 8 years ago

No, the chmod is the last thing the compiler does.

I'll disable it on Windows. You're right that it is unnecessary.

(Does PyOpenCL really work on Windows?)

\ Troels /\ Henriksen

mrakgr commented 8 years ago

I managed to install it, I'll give it a shot tomorrow.

athas commented 8 years ago

I committed something that I think may fix it. You may still want to use the -o option to make foo.fut be built as foo.py, rather than just foo.

mrakgr commented 8 years ago

Had to install pypng via pip and now I am running into this error when I try to execute the example:

C:\futhark\examples>python blur-png.py gottagofast.png --output-file gottagofast-blurred.png
usage: blur-png.py [-h] [-t WRITE_RUNTIME_TO] [-r RUNS]
blur-png.py: error: unrecognized arguments: gottagofast.png --output-file gottagofast-blurred.png

I wonder what this is?

mrakgr commented 8 years ago

Ok, I've added a few print statements and verified that it does not even enter the main function. The error seems to be happening somewhere in the imports.

Edit: Inside blur.py.

Edit2: Right here...

for optarg in parser_result["write_runtime_to"]:
  if runtime_file:
    runtime_file.close()
  runtime_file = open(optarg, "w")
athas commented 8 years ago

You have to use 'futhark-pyopencl --module' when compiling the Futhark program - otherwise you get a standalone program, not a reusable module.

\ Troels /\ Henriksen

mrakgr commented 8 years ago

I just copied the example from the main page. I'll try your suggestion.

Edit: I see that I did not copy from the main page. Nevermind that.

mrakgr commented 8 years ago

Now I am getting this error. Actually, this is the same error as when I tried program compiled by the last version of Futhark, before the latest merge.

C:\futhark\examples>python blur-png.py gottagofast.png --output-file gottagofast-blurred.png
Namespace(filename='gottagofast.png', iterations=1, output_file='gottagofast-blurred.png')
Traceback (most recent call last):
  File "blur-png.py", line 28, in <module>
    main(args.filename, args.output_file, args.iterations)
  File "blur-png.py", line 11, in main
    img = misc.imread(infile, mode='RGB')
TypeError: imread() got an unexpected keyword argument 'mode'

Edit: How strange. It does not seem like the arguments are wrong. I'll play around with this for a bit.

athas commented 8 years ago

That's strange. It's handwritten code that calls a function from the SciPy library. I'm not very knowledgeable about Python, but I suspect that you have a different version of SciPy installed than I did when I wrote that program. I used version 0.17. Which one do you have?

\ Troels /\ Henriksen

mrakgr commented 8 years ago
C:\futhark\examples>pip show scipy
---
Metadata-Version: 2.0
Name: scipy
Version: 0.15.1
Summary: SciPy: Scientific Library for Python

Looking at the documentation in Intellisense, I see that it lacks a mode argument. It is strange that my version is so out of date as I am using the version from Anaconda. I'll upgrade to the latest one.

athas commented 8 years ago

It indeed looks like the 'mode' keyword argument was added in version 0.17. You can try leaving it out and see what happens - it might default to whatever format the image is actually in.

\ Troels /\ Henriksen

mrakgr commented 8 years ago

I'll try that. The scipy upgrade is failing because Anaconda does not seem to have any BLAS libraries with it, so the scipy compilaltion fails. I have no idea what to do about this.

mrakgr commented 8 years ago

No, it did not work out.

C:\futhark\examples>python blur-png.py gottagofast.png --output-file gottagofast-blurred.png
Namespace(filename='gottagofast.png', iterations=1, output_file='gottagofast-blurred.png')
Traceback (most recent call last):
  File "blur-png.py", line 28, in <module>
    main(args.filename, args.output_file, args.iterations)
  File "blur-png.py", line 13, in main
    blurred = b.main(iterations, img)
  File "C:\futhark\examples\blur.py", line 1670, in main
    assert (np.int32(3) == image_mem_1617_ext.shape[np.int32(2)]), 'shape dimension is incorrect for the constant dimension'
AssertionError: shape dimension is incorrect for the constant dimension

I do not suppose there is a way of reading png files that does not depend on Scipy routines?

Edit: I'll try downloading the latest Anaconda, though the one I have now should have arrived with Scipy 0.17.

athas commented 8 years ago

I have sometimes used the pypng library for operating on PNG files: https://pythonhosted.org/pypng/png.html

The reason I didn't use it for the blurring example is that I found it awkward to extract a Numpy array from the generator produced by pypng. I must re-iterate that I'm not much of a Python programmer, so there may be some way.

\ Troels /\ Henriksen

athas commented 8 years ago

I think the reason you get that error is because SciPy produces an array where the size of the innermost (third) dimension is 4 (i.e. contains an alpha channel), where the Futhark program blur.fut explicitly demands an inner dimension of size 3.

You can do some pre-processing in Python to shrink the inner dimension (not sure how, but there's probably a Numpy one-liner), or modify blur.fut to accept an alpha channel (but probably just throw it away).

mrakgr commented 8 years ago

No, it is fine. Most of the errors in this thread seem to be on my own end. I never realized that the Anaconda distribution I had on my system was nearly a year old. I am nearly done reinstalling everything and will try again after I am done.

mrakgr commented 8 years ago

Ok, I finally installed everything that needs to be, but even so, it still does not work.

C:\futhark\examples>python blur-png.py gottagofast.png --output-file gottagofast-blurred.png
Traceback (most recent call last):
  File "blur-png.py", line 27, in <module>
    main(args.filename, args.output_file, args.iterations)
  File "blur-png.py", line 16, in main
    w.write(f, numpy.reshape(blurred.astype(numpy.uint8), (height, width*3)))
  File "C:\Users\Marko\Anaconda2\lib\site-packages\png.py", line 655, in write
    nrows = self.write_passes(outfile, rows)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\png.py", line 804, in write_passes
    extend(row)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\png.py", line 801, in <lambda>
    return lambda sl: f(map(int, sl))
TypeError: int() argument must be a string or a number, not 'Array'

Edit:

        t = numpy.reshape(blurred.astype(numpy.uint8), (height, width*3))
        print type(t)
        print type(f)

Output:

<class 'pyopencl.array.Array'>
<type 'file'>

Edit2: http://stackoverflow.com/questions/35629229/numpy-array-of-arrays-to-pyopencl-array-of-vecs

I'll try converting the pyOpenCl array, manually to a host numpy matrix as soon as the Intellisense database finishes refreshing. That last part always takes an absurd amount of time for some reason.

Edit3:

        t = numpy.reshape(blurred.astype(numpy.uint8), (height, width*3))
        print type(t)
        q = numpy.array(t)
        print type(q)
        w.write(f, q)

I tried making the above modification the last lines of main, but it still fails.

C:\futhark\examples>python blur-png.py gottagofast.png --output-file gottagofast-blurred.png
<class 'pyopencl.array.Array'>
<type 'numpy.ndarray'>
Traceback (most recent call last):
  File "blur-png.py", line 31, in <module>
    main(args.filename, args.output_file, args.iterations)
  File "blur-png.py", line 20, in main
    w.write(f, q)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\png.py", line 655, in write
    nrows = self.write_passes(outfile, rows)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\png.py", line 804, in write_passes
    extend(row)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\png.py", line 801, in <lambda>
    return lambda sl: f(map(int, sl))
TypeError: int() argument must be a string or a number, not 'Array'

From here, I'll move to hacking png.py directly.

athas commented 8 years ago

Interesting! It fails inside the PNG encoding library. Since the function call

w.write(f, numpy.reshape(blurred.astype(numpy.uint8), (height, width*3)))

passes just an array, I am not really sure what could go wrong. If 'height' or 'width' was mistakenly an array and not a scalar, it would fail in the reshape(), not in the call to write().

So... I don't really know what could be wrong here. Maybe your pypng is also old? However, the png.py I have locally seems to contain the same lines 655, 804 and 801 as mentioned in the backtrace.

You could try using the imsave method from SciPy: https://docs.scipy.org/doc/scipy-0.17.0/reference/generated/scipy.misc.imsave.html

If that works, I'll just change the example to use SciPy entirely. It's a bit ugly to use different libraries for reading and writing, I think.

\ Troels /\ Henriksen

mrakgr commented 8 years ago

I did some tests. For some reason, imsave works for when I write the original image to the outfile, but if I pass it the resulting OpenCL array, it freezes up.

Right now I am trying to figure out how to turn that OpenCL array from the main function into a genuine host array, but I am not sure how. I think that at the end of blur.py it is in fact being copied to host synchronously.

I need to do this in order to figure out what the problem is with imsave and whether the problem is there in the first place.

Printing out the blurred variable works fine. Is there a way to force a copy to host and conversion to numpy array?

Also, there is nothing wrong with my version of pypng, I got it straight off pip.

Edit: Actually, it does not print out fine.

[[[array(-76, dtype=int8) array(-53, dtype=int8) array(-12, dtype=int8)]
  [array(-76, dtype=int8) array(-53, dtype=int8) array(-12, dtype=int8)]
  [array(-68, dtype=int8) array(-46, dtype=int8) array(-10, dtype=int8)]
  ...,
  [array(-77, dtype=int8) array(-52, dtype=int8) array(-9, dtype=int8)]
  [array(-71, dtype=int8) array(-49, dtype=int8) array(-12, dtype=int8)]
  [array(-61, dtype=int8) array(-42, dtype=int8) array(-8, dtype=int8)]]

 [[array(-76, dtype=int8) array(-53, dtype=int8) array(-12, dtype=int8)]
  [array(-63, dtype=int8) array(-43, dtype=int8) array(-9, dtype=int8)]
  [array(-51, dtype=int8) array(-35, dtype=int8) array(-8, dtype=int8)]
  ...,
  [array(-66, dtype=int8) array(-45, dtype=int8) array(-10, dtype=int8)]
  [array(-65, dtype=int8) array(-44, dtype=int8) array(-9, dtype=int8)]
  [array(-68, dtype=int8) array(-45, dtype=int8) array(-8, dtype=int8)]]

 [[array(-77, dtype=int8) array(-52, dtype=int8) array(-9, dtype=int8)]
  [array(-52, dtype=int8) array(-36, dtype=int8) array(-8, dtype=int8)]
  [array(-37, dtype=int8) array(-26, dtype=int8) array(-7, dtype=int8)]
  ...,
  [array(-65, dtype=int8) array(-45, dtype=int8) array(-10, dtype=int8)]
  [array(-63, dtype=int8) array(-43, dtype=int8) array(-9, dtype=int8)]
  [array(-71, dtype=int8) array(-49, dtype=int8) array(-12, dtype=int8)]]

 ...,
 [[array(-24, dtype=int8) array(-24, dtype=int8) array(-24, dtype=int8)]
  [array(-77, dtype=int8) array(-78, dtype=int8) array(-77, dtype=int8)]
  [array(-109, dtype=int8) array(-110, dtype=int8) array(-109, dtype=int8)]
  ...,
  [array(-72, dtype=int8) array(-73, dtype=int8) array(-72, dtype=int8)]
  [array(-73, dtype=int8) array(-73, dtype=int8) array(-72, dtype=int8)]
  [array(-77, dtype=int8) array(-79, dtype=int8) array(-82, dtype=int8)]]

 [[array(-20, dtype=int8) array(-21, dtype=int8) array(-21, dtype=int8)]
  [array(-65, dtype=int8) array(-66, dtype=int8) array(-65, dtype=int8)]
  [array(-96, dtype=int8) array(-97, dtype=int8) array(-96, dtype=int8)]
  ...,
  [array(-76, dtype=int8) array(-77, dtype=int8) array(-78, dtype=int8)]
  [array(-72, dtype=int8) array(-73, dtype=int8) array(-74, dtype=int8)]
  [array(-66, dtype=int8) array(-64, dtype=int8) array(-65, dtype=int8)]]

 [[array(-38, dtype=int8) array(-40, dtype=int8) array(-41, dtype=int8)]
  [array(-75, dtype=int8) array(-74, dtype=int8) array(-70, dtype=int8)]
  [array(-96, dtype=int8) array(-97, dtype=int8) array(-96, dtype=int8)]
  ...,
  [array(-67, dtype=int8) array(-69, dtype=int8) array(-70, dtype=int8)]
  [array(-66, dtype=int8) array(-64, dtype=int8) array(-65, dtype=int8)]
  [array(-51, dtype=int8) array(-53, dtype=int8) array(-54, dtype=int8)]]]

Is the numpy matrix a 3D matrix of arrays?

If so, that could explain why the save step is failing.

athas commented 8 years ago

You can do that by calling the .get() method on the returned array - it returns a Numpy array copied from the PyOpenCL array.

\ Troels /\ Henriksen

mrakgr commented 8 years ago

Actually, your suggestion is quite helpful. Wish I could have figured it out on my own.

Now the problem is this:

C:\Users\Marko\Anaconda2\lib\site-packages\scipy\misc\pilutil.py:90: RuntimeWarning: overflow encountered in byte_scalars
  cscale = cmax - cmin
Traceback (most recent call last):
  File "blur-png.py", line 25, in <module>
    main(args.filename, args.output_file, args.iterations)
  File "blur-png.py", line 14, in main
    misc.imsave(outfile,blurred.get())
  File "C:\Users\Marko\Anaconda2\lib\site-packages\scipy\misc\pilutil.py", line 195, in imsave
    im = toimage(arr, channel_axis=2)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\scipy\misc\pilutil.py", line 341, in toimage
    bytedata = bytescale(data, high=high, low=low, cmin=cmin, cmax=cmax)
  File "C:\Users\Marko\Anaconda2\lib\site-packages\scipy\misc\pilutil.py", line 92, in bytescale
    raise ValueError("`cmax` should be larger than `cmin`.")
ValueError: `cmax` should be larger than `cmin`.

The reason for this is, as you will see if you take a look at the values above, is that they are all negative for some reason. I am not sure why this is so.

Edit: Actually, could this be because the unsigned 8-bit ints got converted to signed ones?

mrakgr commented 8 years ago

I finally did it. I was right. There was an invalid conversion error. Take a look:

    return cl.array.Array(self.queue, (rows_1201, cols_1202, np.int32(3)),
                          ct.c_int8, data=out_mem_1676)
    return cl.array.Array(self.queue, (rows_1201, cols_1202, np.uint32(3)),
                          ct.c_uint8, data=out_mem_1676)

When I modified the first ct.c_int8 to the second ct.c_uint8 it started working. This is definitely a bug. I wonder why it worked for you on Linux?

At any rate, I would also suggest a switch to imsave entirely. Here is how it looks like right now:

def main(infile, outfile, iterations):
    b = blur.blur()
    img = misc.imread(infile, mode='RGB')
    (height, width, channels) = img.shape
    blurred = b.main(iterations, img)
    misc.imsave(outfile,blurred.get())

Edit: Also, pyOpenCL arrays should definitely not be passed to the rest of the Python's ecosystem. They should be converted to host arrays on return. The imsave freezes for me otherwise for example and that pypng write error might be related to this as well.

Edit2: While you are fixing this, do make futhark-opencl output the file with the .py extension as well.

athas commented 8 years ago

That does indeed look like a bug. blur.fut operates only with unsigned bytes (u8), so I don't think there should be any array produced with that type. I will take a look.

I have committed your suggested change to blur-png.py.

\ Troels /\ Henriksen

athas commented 8 years ago

Ugh, I think I know what's going on.

Internally, Futhark does not distinguish between signed and unsigned integers. This design is taken from LLVM, and works very well for avoiding meaningless casts that do not change representation.

However, it does cause some friction when interacting with Numpy, which does distinguish between them. For example, you will get an error if you create an array of signed 8-bit integers, then try writing a value that is greater than 127. That's why the former version of blur-png.py contained the call to the .astype() method (which I will now add back).

This problem will take some effort to fix nicely. We will have to remember the "original types" of the entry point functions and apply them in the code generator. Since simple workarounds have proven sufficient so far, it will probably be a while before we get around to adding this bit of polish.

mrakgr commented 8 years ago

That is a bit surprising. How does it manage comparisons if it does not distinguish unsigned and signed integers?

athas commented 8 years ago

There are specific instructions for signed versus unsigned comparisons (and similar for division and the like).

\ Troels /\ Henriksen

athas commented 8 years ago

I think the problems here have been resolved, so closing the issue. Thank you for the patience you've shown with all this broken code!

mrakgr commented 8 years ago

Ok. Do not forget to open an issue for the entry point code generator fix. That one has not been resolved yet.