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.9k
gocon2019.pdf
bokuweb
5
14k
ファミコンエミュレータの創り方
bokuweb
58
46k
component test
bokuweb
7
5.2k
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
Practical Orchestrator
shlominoach
192
12k
Optimizing for Happiness
mojombo
378
71k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
Tell your own story through comics
letsgokoyo
1
1.1k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
270
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
540
YesSQL, Process and Tooling at Scale
rocio
174
15k
Ruling the World: When Life Gets Gamed
codingconduct
0
420
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Music & Morning Musume
bryan
48
7.5k
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