emscripten_night_7.pdf

83c268781ec54605af1f7b866d7de3ad?s=47 bokuweb
April 19, 2019
720

 emscripten_night_7.pdf

83c268781ec54605af1f7b866d7de3ad?s=128

bokuweb

April 19, 2019
Tweet

Transcript

  1. &NTDSJQUFO8FC"TTFNCMZOJHIU ը૾ॲཧͰൺ΂Δ 8FC"TTFNCMZ !CPLVXFC

  2. !CPLVXFC IUUQCMPHCPLVXFCNF w 8FCϑϩϯτΤϯυΤϯδχΞ w ૊ΈࠐΈϋʔυ΢ΣΞΤϯδχΞ w ࢁʹੜଉ CPLVXFC ࣗݾ঺հ

  3. CPLVXFCSVTUZOFT IUUQTHJUIVCDPNCPLVXFCSVTUZOFT

  4. SFHWJ[SFHDMJ

  5. NBQCPYQJYFMNBUDI

  6. XBTNԽͯ͠Έͯ Ͳ͏ͳΔ͔ΈͯΈΔ

  7. QJYFMNBUDIͷಈ͖ Ұக

  8. QJYFMNBUDIͷಈ͖ ෆҰக

  9. QJYFMNBUDIͷಈ͖

  10. for(let y = 0; y < height; y++) { for(let

    x = 0; x < width; x++) { if (৭Ұக) { ੺͘ඳը } else { ബ͘ඳը } } } QJYFMNBUDIͷಈ͖
  11. +4XBTNͷσʔλ΍ΓऔΓͲ͏͢Δ͔ ϦχΞϝϞϦ ൪஍ ೖྗը૾ ೖྗը૾̎ ग़ྗը૾

  12. +BWB4DSJQU

  13. #ZUF NJOJGZޙ +BWB4DSJQU

  14. $

  15. extern "C" uint32_t pixelmatch(const uint8_t *img1, const uint8_t *img2,uint32_t width,ɹuint32_t

    height, uint8_t *output){ float maxDelta = 35215 * 0.1 * 0.1; uint32_t diff = 0; for (uint32_t y = 0; y < height; y++) { for (uint32_t x = 0; x < width; x++) { uint32_t pos = (y * width + x) * 4; float delta = colorDelta(img1, img2, pos, pos, false); if (delta > maxDelta) { drawPixel(output, pos, 255, 0, 0); diff++; } else if (output) { uint8_t val = grayPixel(img1, pos, 0.1); drawPixel(output, pos, val, val, val); } } } return diff; } $
  16. emcc -O3 -s ALLOW_MEMORY_GROWTH=1 \ -s EXPORTED_FUNCTIONS=[‘_pixelmatch’] \ -o pixelmatch.js

    -s pixelmatch.cpp $
  17. #ZUF ͱάϧʔίʔυͷKT͕,# ࠓճະ࢖༻ 0ͷ৔߹͸,# $

  18. 3VTU

  19. #[no_mangle] pub extern fn pixelmatch(img1: *mut u8, img2: *mut u8,

    width: u32, height: u32, output: *mut u8) -> u32 { let buf1: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(img1, (width * height * 4) as usize) }; let buf2: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(img2, (width * height * 4) as usize) }; let out: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(output, (width * height * 4) as usize) }; let max_delta = 35215.0 * 0.1 * 0.1; let mut diff_count = 0; for y in 0..height { for x in 0..width { let pos = ((y * width + x) * 4) as u32; let delta = color_delta(buf1, buf2, pos, pos, false); if delta > max_delta { draw_pixel(out, pos, 255, 0, 0, 255); diff_count += 1; } else { let y = gray_pixel(buf1, pos, 0.1); draw_pixel(out, pos, y, y, y, 255); } } } diff_count } 3VTU
  20. XBTNQBDLCVJME 3VTU

  21. ,#ZUF 3VTU

  22. #![no_std] #[no_mangle] pub extern fn pixelmatch( img1: *mut u8, img2:

    *mut u8, width: u32, height: u32, output: *mut u8) -> u32 { … } 3VTU
  23.  #ZUF ˣ,#ZUF 3VTU

  24. wasm-opt -O3 -o \ pkg/pixelmatch_optimized.wasm \ pkg/pixelmatch_bg.wasm * macͳΒbrew install

    binaryen ͰೖΔ 3VTU
  25.  #ZUF ˣ#ZUF 3VTU

  26. wasm-strip pkg/ pixelmatch_optimized.wasm * https://github.com/WebAssembly/wabt ʹؚ·Ε͍ͯΔ 3VTU

  27.  #ZUF ˣ#ZUF 3VTU

  28. "TTFNCMZ4DSJQU

  29. export function pixelmatch(img1: u32,img2: u32, width: u32, height: u32): u32

    { let maxDelta = (35215 as f32) * 0.1 * 0.1; let diff = 0; for (let y: u32 = 0; y < height; y++) { for (let x: u32 = 0; x < width; x++) { let pos = (y * width + x) * 4; let delta = colorDelta(img1, img2, pos, pos, false); if (delta > maxDelta) { diff++; drawPixel(img1 + img2, pos, 255, 0, 0); } else { let val = grayPixel(pos, 0.1) as u32; drawPixel(img1 + img2, pos, val, val, val); } } } return diff; } "TTFNCMZ4DSJQU
  30. function get(addr: u32, offset: u32): u8 { return load<u8>(addr +

    offset); } function set(addr: u32, offset: u32, value: u8): void { store<u8>(addr + offset, value); } "TTFNCMZ4DSJQU
  31. asc assembly/index.ts -b build/optimized.wasm \ -t build/optimized.wat --validate —optimize \

    —importMemory "TTFNCMZ4DSJQU
  32. #ZUF "TTFNCMZ4DSJQU

  33. $ISPNF 4BGBSJ 'JSFGPY      1.6 GHz

    Intel Core i5 16 GB 2133 MHz LPDDR3 ops / sec Bigger is better PQTTFD PQTTFD PQTTFD PQTTFD $ 3VTU "4 +4 PQTTFD PQTTFD PQTTFD PQTTFD $ 3VTU "4 +4 PQTTFD PQTTFD PQTTFD PQTTFD $ 3VTU "4 +4 #FODINBSL
  34. (module (type $FUNCSIG$iiiii (func (param i32 i32 i32 i32) (result

    i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$fff (func (param f32 f32) (result f32))) (type $FUNCSIG$ffff (func (param f32 f32 f32) (result f32))) (type $FUNCSIG$viiiii (func (param i32 i32 i32 i32 i32))) (type $FUNCSIG$viii (func (param i32 i32 i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$fiii (func (param i32 i32 i32) (result f32))) (type $FUNCSIG$fi (func (param i32) (result f32))) (import "env" "memory" (memory $0 0)) (table $0 1 funcref) (elem (i32.const 0) $null) (export "memory" (memory $0)) (export "table" (table $0)) (export "pixelmatch" (func $assembly/index/pixelmatch)) (func $assembly/index/get (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) local.get $0 local.get $1 i32.add i32.load8_u ) "TTFNCMZ4DSJQU
  35. @inline "TTFNCMZ4DSJQU

  36. @inline function get(addr: u32, offset: u32): u8 { return load<u8>(addr

    + offset); } @inline function set(addr: u32, offset: u32, value: u8): void { store<u8>(addr + offset, value); } "TTFNCMZ4DSJQU
  37. #ZUF ˢ#ZUF "TTFNCMZ4DSJQU

  38. $ISPNF 4BGBSJ 'JSFGPY      1.6 GHz

    Intel Core i5 16 GB 2133 MHz LPDDR3 ops / sec Bigger is better PQTTFD PQTTFD PQTTFDˢ PQTTFD $ 3VTU "4 +4 PQTTFD PQTTFD PQTTFDˢ PQTTFD $ 3VTU "4 +4 PQTTFD PQTTFD PQTTFDˢ PQTTFD $ 3VTU "4 +4 #FODINBSL ࠶
  39. (module (type (;0;) (func (param i32 i32 i32 i32) (result

    f32))) (type (;1;) (func (param i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory (;0;) 256)) (func (;0;) (type 0) (param i32 i32 i32 i32) (result f32) (local i32 i32 i32 i32 i32 i32 f32 f32 f32 f32 f32 f32 f32 f32) local.get 0 local.get 2 i32.const 2 i32.add i32.add i32.load8_s local.tee 4 local.get 1 $ DPMPS%FMUB
  40. αΠζ H[JQޙ      ops / sec

    Smaller is better $ 3VTU "TTFNCMZ4DSJQU +BWB4DSJQU #ZUF #ZUF #ZUF #ZUF
  41. ·ͱΊ "ؾʹ͠ͳ͍ͱ+4ΑΓେ͖͘ͳͬͨΓ஗͘ͳͬͨΓ͢Δ ৔߹͕͋ΔΑ "ϒϥ΢βʹΑͬͯ͸͔ͳΓ଎͘ͳΔʢ͔΋ʣ͠ ɹϒϥ΢βؒͰͷ଎౓͕ࠩࠓճ͸େ͖͘ͳ͔ͬͨΑ

  42. ͋Γ͕ͱ͏͍͟͝·ͨ͠ CPLVXFCXBTNQJYFMNBUDI