Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
emscripten_night_7.pdf
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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.6k
gocon2019.pdf
bokuweb
5
13k
ファミコンエミュレータの創り方
bokuweb
58
45k
component test
bokuweb
7
5.1k
Featured
See All Featured
Heart Work Chapter 1 - Part 1
lfama
PRO
7
36k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Building Applications with DynamoDB
mza
96
7.1k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
200
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
860
KATA
mclloyd
PRO
35
15k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
56k
How to train your dragon (web standard)
notwaldorf
97
6.7k
A designer walks into a library…
pauljervisheath
211
24k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
170
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
180
The Invisible Side of Design
smashingmag
302
52k
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