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
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.7k
gocon2019.pdf
bokuweb
5
13k
ファミコンエミュレータの創り方
bokuweb
58
46k
component test
bokuweb
7
5.2k
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
440
Building AI with AI
inesmontani
PRO
1
1.1k
Mobile First: as difficult as doing things right
swwweet
225
10k
Facilitating Awesome Meetings
lara
57
7.1k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Designing Experiences People Love
moore
143
24k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
First, design no harm
axbom
PRO
2
1.2k
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