Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
emscripten_night_7.pdf
Search
bokuweb
April 19, 2019
1.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
emscripten_night_7.pdf
bokuweb
April 19, 2019
More Decks by bokuweb
See All by bokuweb
1000 行で実現する Linux on Browser
bokuweb
17
9.8k
gocon2019.pdf
bokuweb
5
13k
ファミコンエミュレータの創り方
bokuweb
58
46k
component test
bokuweb
7
5.2k
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Are puppies a ranking factor?
jonoalderson
2
3.9k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
280
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
330
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
350
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
How to make the Groovebox
asonas
2
2.4k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
490
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Transcript
&NTDSJQUFO8FC"TTFNCMZOJHIU ը૾ॲཧͰൺΔ 8FC"TTFNCMZ !CPLVXFC
!CPLVXFC IUUQCMPHCPLVXFCNF w 8FCϑϩϯτΤϯυΤϯδχΞ w ΈࠐΈϋʔυΣΞΤϯδχΞ w ࢁʹੜଉ CPLVXFC ࣗݾհ
CPLVXFCSVTUZOFT IUUQTHJUIVCDPNCPLVXFCSVTUZOFT
SFHWJ[SFHDMJ
NBQCPYQJYFMNBUDI
XBTNԽͯ͠Έͯ Ͳ͏ͳΔ͔ΈͯΈΔ
QJYFMNBUDIͷಈ͖ Ұக
QJYFMNBUDIͷಈ͖ ෆҰக
QJYFMNBUDIͷಈ͖
for(let y = 0; y < height; y++) { for(let
x = 0; x < width; x++) { if (৭Ұக) { ͘ඳը } else { ബ͘ඳը } } } QJYFMNBUDIͷಈ͖
+4XBTNͷσʔλΓऔΓͲ͏͢Δ͔ ϦχΞϝϞϦ ൪ ೖྗը૾ ೖྗը૾̎ ग़ྗը૾
+BWB4DSJQU
#ZUF NJOJGZޙ +BWB4DSJQU
$
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; } $
emcc -O3 -s ALLOW_MEMORY_GROWTH=1 \ -s EXPORTED_FUNCTIONS=[‘_pixelmatch’] \ -o pixelmatch.js
-s pixelmatch.cpp $
#ZUF ͱάϧʔίʔυͷKT͕,# ࠓճະ༻ 0ͷ߹,# $
3VTU
#[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
XBTNQBDLCVJME 3VTU
,#ZUF 3VTU
#![no_std] #[no_mangle] pub extern fn pixelmatch( img1: *mut u8, img2:
*mut u8, width: u32, height: u32, output: *mut u8) -> u32 { … } 3VTU
#ZUF ˣ,#ZUF 3VTU
wasm-opt -O3 -o \ pkg/pixelmatch_optimized.wasm \ pkg/pixelmatch_bg.wasm * macͳΒbrew install
binaryen ͰೖΔ 3VTU
#ZUF ˣ#ZUF 3VTU
wasm-strip pkg/ pixelmatch_optimized.wasm * https://github.com/WebAssembly/wabt ʹؚ·Ε͍ͯΔ 3VTU
#ZUF ˣ#ZUF 3VTU
"TTFNCMZ4DSJQU
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
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
asc assembly/index.ts -b build/optimized.wasm \ -t build/optimized.wat --validate —optimize \
—importMemory "TTFNCMZ4DSJQU
#ZUF "TTFNCMZ4DSJQU
$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
(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
@inline "TTFNCMZ4DSJQU
@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
#ZUF ˢ#ZUF "TTFNCMZ4DSJQU
$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 ࠶
(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
αΠζ H[JQޙ ops / sec
Smaller is better $ 3VTU "TTFNCMZ4DSJQU +BWB4DSJQU #ZUF #ZUF #ZUF #ZUF
·ͱΊ "ؾʹ͠ͳ͍ͱ+4ΑΓେ͖͘ͳͬͨΓ͘ͳͬͨΓ͢Δ ߹͕͋ΔΑ "ϒϥβʹΑ͔ͬͯͳΓ͘ͳΔʢ͔ʣ͠ ɹϒϥβؒͰͷ͕ࠩࠓճେ͖͘ͳ͔ͬͨΑ
͋Γ͕ͱ͏͍͟͝·ͨ͠ CPLVXFCXBTNQJYFMNBUDI