Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using wasm to accelerate PixelManipulation.js #1093

Merged
merged 43 commits into from
Jun 21, 2019
Merged

Conversation

Divy123
Copy link
Member

@Divy123 Divy123 commented May 29, 2019

Fixes #400

Make sure these boxes are checked before your pull request (PR) is ready to be reviewed and merged. Thanks!

  • tests pass -- look for a green checkbox ✔️ a few minutes after opening your PR -- or run tests locally with npm test
  • code is in uniquely-named feature branch and has no merge conflicts
  • PR is descriptively titled
  • ask @publiclab/is-reviewers for help, in a comment below

We're happy to help you get this ready -- don't be afraid to ask for help, and don't be discouraged if your tests fail at first!

If tests do fail, click on the red X to learn why by reading the logs.

Please be sure you've reviewed our contribution guidelines at https://publiclab.org/contributing-to-public-lab-software

Thanks!

@Divy123
Copy link
Member Author

Divy123 commented May 29, 2019

The C code is:

int getPixels(int , int , int );

int setPixels(int, int, int, int);

int * changePixel(int, int, int, int, int, int);

void paceOp();

void consoleLog(int);

void manipulatePixel(int width, int height, int inBrowser, int test){
  consoleLog(100);
  for (int x = 0; x < width; x++) {
        for (int y = 0; y <height; y++) {
          int* pixel =changePixel(
            getPixels(x, y, 0),
            getPixels(x, y, 1),
             getPixels(x, y, 2),
             getPixels(x, y, 3),
            x,
            y
          );
          setPixels(x, y, 0, pixel[0]);
          setPixels(x, y, 1, pixel[1]);
          setPixels(x, y, 2, pixel[2]);
          setPixels(x, y, 3, pixel[3]);

          if (!inBrowser && !test) paceOp();
        }
      }
}

@Divy123
Copy link
Member Author

Divy123 commented May 31, 2019

@jywarren I have sucessfully made the first transition from js to wasm on the commented out code involving loops, as you can see.

Please provide your feedback on the same. Also, can you please provide some information on pace.op() as I have to use that in wasm but am not familiar with that.

Thanks!!

@jywarren
Copy link
Member

Oh, i'm not familiar with pace.op() either - can you use the blame feature to see who added it?

Did you then figure out the issue you'd had trouble with earlier? If so, congrats!!!

Did you look at why tests are failing?

One thing you might consider is looking at the benchmarks:

https://travis-ci.org/publiclab/image-sequencer/jobs/539546409#L1318

And, what about setting up the tests to run both with WebAssembly and without (using an options flat like withWebAssembly = true, so that we get 2x benchmarks and can compare across? Ensuring that the code runs with and without the webassembly changes would be great to have as an option and also great to codify in the tests. What do you think?

@jywarren
Copy link
Member

Huh - this error is because different offsets are supposed to change the output, but it doesn't seem to:

https://travis-ci.org/publiclab/image-sequencer/jobs/539546409#L1173

@Divy123
Copy link
Member Author

Divy123 commented Jun 1, 2019

@tech4GT , can you elaborate something about the use of pace and what is pace.op() ?

@Divy123
Copy link
Member Author

Divy123 commented Jun 1, 2019

Thanks @jywarren . Looking into the issues now.

@tech4GT
Copy link
Member

tech4GT commented Jun 1, 2019

Hi, pace is actually used for drawing the progress bars, I originally planned to fork pace and make some changes specific to Image sequencer and enhance the whole feature but never got around to it.
pace.op() actually represents one tick of the progress bar on the console.

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Thanks @tech4GT .
@jywarren what's happening in this is I was using WebAssembly.instantiateStreaming method which works only for browsers which I came to know today only 😅 .

I will be using another function and updating the PR as soon as possible.

@jywarren
Copy link
Member

jywarren commented Jun 2, 2019 via email

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Just one thing here, I am able to see is options.inBrowser is true while running tests. Is it correct and if yes, why are we doing this?

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

The issue I am facing is fs module not working.
When I console.log fs, I see {} and fs.readFileSync() is undefined inside pixelManipulation.js file while running tests.

@jywarren , @tech4GT can you please help me with this?

I don't know but I think this is because of tests are running in browser mode and fs is not recognised there.

@harshkhandeparkar
Copy link
Member

@Divy123 do you have a code snippet?

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Yes sharing now

if (options.changePixel) {
      isDone = true;
      /* Allows for Flexibility
       if per pixel manipulation is not required */
      const fs = require('fs');
      console.log(fs.readFileSync)
      var source = fs.readFileSync('./p1.wasm');
      var typedArray = new Uint8Array(source);

@harshkhandeparkar
Copy link
Member

What is the test command? which file tests this? all(most) of them?

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Basically run() is not working as it involves execution of this piece of code in some modules of ours.

@harshkhandeparkar
Copy link
Member

So the test file is run.js?

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Test file is image-sequencer.js in test folder.

@harshkhandeparkar
Copy link
Member

Ok. Looking into it

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Thanks a lot !!

@harshkhandeparkar
Copy link
Member

In this command

TEST=true istanbul cover tape test/core/*.js test/core/ui/user-interface.js test/core/modules/*.js | tap-spec; browserify test/core/sequencer/image-sequencer.js test/core/sequencer/chain.js test/core/sequencer/meta-modules.js test/core/sequencer/replace.js test/core/sequencer/import-export.js test/core/sequencer/run.js test/core/sequencer/dynamic-imports.js test/core/util/*.js test/core/sequencer/benchmark.js | tape-run --render=\"tap-spec\"

the file is browserified, does it get browserified properly without errors?

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

That I am unaware of now.
Posting error stack here:

 run() runs the sequencer and returns output to callback

    {}
    TypeError: fs.readFileSync is not a function
        at http://localhost:41821/bundle.js:91964:23
        at Image.img.onload (http://localhost:41821/bundle.js:25664:5)
npm ERR! Test failed.  See above for more details.

@harshkhandeparkar
Copy link
Member

It is browserified first. Maybe while it is browserified, fs module isn't appended. Try running the file directly in CLI.

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

Doing it now!!

@Divy123
Copy link
Member Author

Divy123 commented Jun 2, 2019

No benefits!!

@jywarren
Copy link
Member

Ah but:

I kind of had that feeling about pace! It can be disabled with ui false now!

That wasn't responding to our question about removing the browser-environment meta-module test. It might be a suggestion about how to work around the error and re-instate the browser meta-module test. Maybe this is what you did just now? Let me look! Thanks!

Copy link
Member

@jywarren jywarren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, made a few suggestions and we should be OK. I do think it's worthwhile trying to identify the environment where this should run ahead of time, instead of using catch to just default to the fallback for /any/ error that may occur -- but at least logging out the error will help us better understand what actually happened instead of assuming it's just not the environment we want. How does this sound?

try {
var pace = require('pace')(pixels.shape[0] * pixels.shape[1]);
} catch (e) {
options.inBrowser = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a good assumption? If our error is TypeError: fs.readFileSync is not a function shouldn't we try to work around it by disabling ui as @tech4GT suggested?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disbling ui is not actually working here.

src/modules/_nomodule/PixelManipulation.js Show resolved Hide resolved
Copy link
Member

@tech4GT tech4GT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Divy123 @jywarren I think pace is not very well maintained, and looking through their github it's a good idea to move away from that. Let's completely deprecate pace based progress reporting and replace it with a prompt for now.
@Divy123 I am available throughout the weekend if you need any help with that, if you need me to do it, that is OK too! Anyway, we also need to update the associated documentation.
I hope this also solves the issues we were having over on the is-app.
You have done amazing work here, we'll soon merge this!!

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

The documentation is a part of contributing.md file mainly.
Also the progressObj is deeply integrated with the system, and that API is fine.
I'll try to explain:
What happens is that we have a progressObj which is a normal spinner. Pixel manipulation overrides that with it's own pace object and uses that to report progress. The idea was to make this customizable on a module per module basis. So let's first try removing 'pace', the way to do that will be to remove all code associated with it inside pixelManipulation. Also, inside every module which uses it, we would have to remove the code which stops the spinner.
Then we can disable the spinner too, maybe based on ui value.
@Divy123 Does that make sense?

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

Ya sure @tech4GT, looking into it.

Thanks a lot!!

Copy link
Member

@tech4GT tech4GT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work here! Let's just make sure our tests pass and the travis builds. Once that is done, we should be ready to merge! 🎉

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

@tech4GT tests have passed!!

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

Great! @jywarren I think this is ready to merge then! I had a call with Divy, and he is going to refactor the progress reporting API shortly, but for now this should be enough!! Awesome!
Also, @Divy123 Can you post a screenshot of your terminal after you run it through the CLI

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

@tech4GT are you talking of the tests?

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

No, just cd into image sequencer and run this

node ./index.js -s "brightness"

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

Sure!!

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

I just want to make sure that the spinner is working fine now!

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

I am getting

Can't read file.

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

Hmm, just a sec.

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

Oh, you have to give an image as well! It does not use the sample image automatically!

node ./index.js -i "<path-to-image>" -s "brightness"

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

Screenshot from 2019-06-21 18-41-29
@tech4GT here we are!!

@Divy123
Copy link
Member Author

Divy123 commented Jun 21, 2019

Also the output is present in ./output

@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

This looks great!! That is exactly what we expected!
cc @jywarren

@jywarren
Copy link
Member

Perfect. Thanks both very much for your thoroughness, patience, care, and excellence! I'm so happy to merge this! 🎉

@jywarren jywarren merged commit 30659d4 into publiclab:main Jun 21, 2019
@tech4GT
Copy link
Member

tech4GT commented Jun 21, 2019

Awesome! 🎉
@jywarren I'll pull these changes into is-app. Maybe this will solve our problems there too!!

@jywarren
Copy link
Member

jywarren commented Jun 21, 2019 via email

@skilfullycurled
Copy link

This was a really great thread to watch unfold. Congratulations on figuring everything out. It was really cool to to see the real time collaboration!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

explore acceleration w WebAssembly
7 participants