์๋ ํ์ธ์,
Float32Array
๋ฒํผ์ 1024๊ฐ์ f32
๊ฐ์ด ์ ์ฅ๋์ด ์๊ณ WASM ๊ธฐ๋ฐ DSP ์ฝ๋์ ์ํด ์ฒ๋ฆฌ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ค๊ณ ์์ํด ๋ด
์๋ค. :)
๋๋ ์ฌ์ ํ WebAssembly์ ์ต์ํ์ง ์์ต๋๋ค. ์ ๋ ฅํ ์ซ์ ๊ฐ๋ง ๋ด๋ณด๋ธ WASM ํจ์์ ์ธ์๋ก ์ ๋ฌํ ์ ์๋ค๋ ๊ฒ์ ์ดํดํ์ต๋๋ค. ๊ทธ๊ฒ์ ๋์๊ฒ ์๋ฏธ๊ฐ ์์ผ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ธฐ๋ก ๊ฒฐ์ ํ ์ด์ ์ ๋๋ค. ๋๋ ๊ทธ๊ฑฐ ๊ด์ฐฎ์๋ฐ...
๋ฐ๋ผ์ 1024๊ฐ์ ๊ฐ์ ์ ๋ฌํ๊ธฐ ์ํด .memory
์ง์ ํ ๋นํฉ๋๋ค. ์ข๋ค:
const mem = exports.memory.buffer;
const F32 = new Float32Array(mem);
F32[0] = 31337.777;
์ด๊ฒ์ ์ฌ๋ฏธ์์ง๋ง ๋ชจ๋ ๊ฐ์ ํ ๋นํ๋ ค๋ฉด ๋ชจ๋ ๊ฐ์ ๋ฐ๋ณตํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋นํด์ผ ํฉ๋๋ค. ๊ธ์, ์ด๋ป๊ฒ ๋ณด๋ฉด ์ฑ๋ฅ โโ๋ฉด์์ ์๋ชป๋ ๋๋์
๋๋ค. ๋๋ ๋ค์ดํฐ๋ธ impl์ ๊ธฐ๋ํ์ ๊ฒ์
๋๋ค. ๋๋ฅผ ์ํด ๊ทธ๋ ๊ฒ ํ๊ธฐ ์ํด. ์ถ์ฒ ์ ํค data
์์ memoryDescriptor
์ ์ธ์ WebAssembly.Memory
์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ด๊ธฐํ ํ ์ ์์ฑ์ ArrayBuffer
.
์, ๊ทธ๋ผ ์ ๋ WASM ํจ์ ํธ์ถ์ ํ๊ณ WASM impl์ ์คํํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ง์ ์ฒ๋ผ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ค์ ์ฐ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ DSP ๋ฃจํ ๋ด๋ถ์์ ๋ฐ์ํ๋ฏ๋ก ๋ด๊ฐ ๋ณผ ์ ์๋ ํ WASM ์ฝ๋ ๋ด๋ถ์ ์ค๋ฒํค๋๊ฐ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด์ JS ์ปจํ
์คํธ๋ก ๋์๊ฐ ํ ๋ชจ๋ ๊ฐ์ ์ฝ๊ณ ๋ ๋ค๋ฅธ JS ๊ธฐ๋ฐ ๋ฐ์ดํฐ ํํ์ ๊ตฌ์ฑํ๊ธฐ ์ํด ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ค์ ๋ฐ๋ณตํด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ ๋ ๋๋ ๋ค์ดํฐ๋ธ ์ํ์ ๊ธฐ๋ํ์ต๋๋ค. ์ด ๋ชฉ์ ์ผ๋ก๋ ์ฐธ์ํฉ๋๋ค. memory.read(Float32Array)
์ ๊ฐ์ ๊ฒ์ด ๋ฒํผ ๋ฐ์ดํฐ๋ฅผ Float32Array
๋ฐํํ์ฌ ํฌ์ธํฐ์ ๋ฐ๋ณต ๋ฏธ๋ก๋ฅผ ์ถ์ํํฉ๋๋ค.
๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์น๊ณ ์์ต๋๊น?
๋ฐฉ๊ธ ๊ฐ๊ณผํ ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ WASM๊ณผ ์ฃผ๊ณ ๋ฐ๋ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๋ฏธ๋ฆฌ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์๋ก
JavaScript์ WebAssembly ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ ์ง ์๋๋ฉด WebAssembly๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋๋ก ํ ์ง ๊ฒฐ์ ํด์ผ ํฉ๋๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๋ ค๋ฉด for
๋ฃจํ๋ฅผ ์ง์ ์์ฑํ๋ ๋์ TypedArray.prototype.set() ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
let instance = ...;
let myJSArray = new Float32Array(...);
let length = myJSArray.length;
let myWasmArrayPtr = instance.exports.allocateF32Array(length);
let myWasmArray = new Float32Array(instance.exports.memory.buffer, myWasmArrayPtr, length);
// Copy data in to be used by WebAssembly.
myWasmArray.set(myJSArray);
// Process the data in the array.
instance.exports.processF32Array(myWasmArrayPtr, length);
// Copy data out to JavaScript.
myJSArray.set(myWasmArray);
WebAssembly๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ WebAssembly.Memory
๋ฒํผ์ ๋ํ ๋ณด๊ธฐ๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ JavaScript ํจ์์๋ ์ ๋ฌํ ์ ์์ต๋๋ค.
let instance = ...;
let length = ...;
let myArrayPtr = instance.exports.allocateF32Array(length);
let myArray = new Float32Array(instance.exports.memory.buffer, myArrayPtr, length);
// Use myArray as a normal Float32Array in JavaScript, fill in data, etc.
...
// Process the data in the array.
instance.exports.processF32Array(myArrayPtr, length);
// No need to copy data back to JavaScript, just use myArray directly.
๋ํ embind ์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ข ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์, @binji๋ ๊ฐ์ฌํฉ๋๋ค. ๋ฉ์ง๋ค์. ์ ๊ฐ ์ฐพ๋ ๋ฐ๋ก ๊ทธ ์ ํ์ ๋๋ค. ๋ํ ์๊ฐ์ ๋ด์ด ์์ ์ฝ๋๋ฅผ ์์ฑํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ๋ ๋งค์ฐ ๋์์ด ๋ฉ๋๋ค. ์ค๋ ์ ๋ ์ ์๋ํ๊ณ Loader impl์ ๋ํ ๋ช ๊ฐ์ง ๊ฐ์ ์ฌํญ์ ์์ฒญํฉ๋๋ค. https://github.com/AssemblyScript/assemblyscript์์ WASM๊ณผ ์ธํฐํ์ด์คํ๋ ๋ฐ ์ฌ์ฉ ์ค์ ๋๋ค.
์ด์ ๊ด๋ จํ์ฌ webassembly.org์์ ๋ฌธ์๋ฅผ ํ์ฅํ ์ ์๋ ์ต์ ์ด ์์ต๋๊น?
์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
https://webassembly.org/docs/web/
๊ฐ๋ฅํ๋ค๋ฉด ๊ธฐ๊บผ์ด ๊ทธ๋ ๊ฒ ํ๊ฒ ๋ค.
์ฌ๊ธฐ์์ ์ค๋ช ํ๋ ๊ฒ๋ ์ข์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory
@binji ์ฃผ์ ๊ฐ ์๋ ๊ฒฝ์ฐ ํ๋ก์ ํธ์ ๋ํด ์์ง ์์ง ๋ชปํ๋ค๋ฉด https://github.com/torch2424/wasmBoy๋ฅผ ์ข์ํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํ๋ก์ ํธ๋ for ๋ฃจํ๋ฅผ ์ฌ์ฉํ์ฌ ROM ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ค์ ํ๊ธฐ ๋๋ฌธ์ ์ ์ํ ์๋ฃจ์ ์ ์ด์ ์ ์ป์ ์๋ ์์ต๋๋ค.
์ด์ ๊ด๋ จํ์ฌ webassembly.org์์ ๋ฌธ์๋ฅผ ํ์ฅํ ์ ์๋ ์ต์ ์ด ์์ต๋๊น?
์ด ๋ณ๊ฒฝ ์ฌํญ๊ณผ ํจ๊ป webassembly.org๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํ๋ค๋ ๋ฐ ๋์ํ์ต๋๋ค. ๋์์ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์๋ ๋ฌธ์๋ ์ฌ์ ํ ์์ง๋ง ์ฌ์ ๋ฆฌํฌ์งํ ๋ฆฌ๋ ํจ์ฌ ์ต์ ์ด๊ณ ์ ํํฉ๋๋ค.
๋ ๋ง์ ์น ๊ฐ๋ฐ์๊ฐ webassembly.org๋ณด๋ค ํด๋น ์ฌ์ดํธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ผ๋ ์ ์ ๊ณ ๋ คํ๋ฉด MDN์ ๋ช ๊ฐ์ง ์์ ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ๋ ์ฝ๊ณ ๋ ๋์ ๊ฒ์ ๋๋ค.
์ฃผ์ ์์ ๋ฒ์ด๋ ์์ง ํ๋ก์ ํธ์ ๋ํด ์์ง ๋ชปํ๋ค๋ฉด https://github.com/torch2424/wasmBoy๋ฅผ ์ข์ํ ์ ์์ต๋๋ค.
์, @torch2424๋ฅผ ์๋๋ค. :-) ์ ๋ง์ wasm ๊ธฐ๋ฐ ๊ฒ์๋ณด์ด ์๋ฎฌ๋ ์ดํฐ๋ ์์ต๋๋ค: https://github.com/binji/binjgb
๋ ๋ง์ ์น ๊ฐ๋ฐ์๊ฐ webassembly.org๋ณด๋ค ํด๋น ์ฌ์ดํธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ผ๋ ์ ์ ๊ณ ๋ คํ๋ฉด MDN์ ๋ช ๊ฐ์ง ์์ ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ๋ ์ฝ๊ณ ๋ ๋์ ๊ฒ์ ๋๋ค.
์๊ฒ ์ต๋๋ค. ์ค๋ ๋ฐค ์ ๋ฐ์ดํธ๋ฅผ ๊ฒ์ํ๊ฒ ์ต๋๋ค. ๊ณต๊ฐ๋๋์ง ์์๋ณด๊ฒ ์ต๋๋ค.
์, @torch2424๋ฅผ ์๋๋ค. :-) ์ ๋ง์ wasm ๊ธฐ๋ฐ ๊ฒ์๋ณด์ด ์๋ฎฌ๋ ์ดํฐ๋ ์์ต๋๋ค: https://github.com/binji/binjgb
ํํ, ๋ฉ์ง๋ค! ๋ฐํํ๊ฒ ์ต๋๋ค. ์๋ํด ๋ณด์ธ์ :) ์๋ฎฌ๋ ์ดํฐ๋ Zelda - Link's Awakening์์ ์นผ์ ์ป์ ๋ ์ถฉ๋ํ์ง ์์ต๋๋ค. (ํด๋ณ์์) ;))
๋๋ wasmBoy์์๋ ์ถฉ๋์ ๊ณ ์น ์๊ฐ์ ์ฐพ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. :)
์ด๋ด! wasmboy๋ฅผ ์ฐพ์์ต๋๋ค! ๐ ๋ค, @binji ์ ์๋ฎฌ๋ ์ดํฐ๊ฐ ํ์คํ ๋ ์ ํ
ํผ๋๋ฐฑ์ ๊ธฐ๋ฐ์ผ๋ก ๋ช ๊ฐ์ง ๋ฒ๊ทธ๋ฅผ ์ด์์ต๋๋ค.
https://github.com/torch2424/wasmBoy/issues/141 - ๋ฉ๋ชจ๋ฆฌ ์ ๋ฌ
https://github.com/torch2424/wasmBoy/issues/142 - Zelda Crash(์คํฌ๋ฆฐ์ท๊ณผ ํจ๊ป ์๋ํฉ๋๋ค)
์ด์จ๋ , ๋ํ/๋ฌธ์ ๋ฅผ ํ์ ์ํค๊ณ ์ถ์ง ์๋ค๋ฉด ๋ด๊ฐ ์ฐ ๋ฌธ์ ๋ก ๋์ด๊ฐ ๊ฒ์ ๋๋ค. ํ์ง๋ง ํผ๋๋ฐฑ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! ๐
WebAssembly๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ WebAssembly.Memory ๋ฒํผ์ ๋ํ ๋ณด๊ธฐ๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ JavaScript ํจ์์๋ ์ ๋ฌํ ์ ์์ต๋๋ค.
ํ ๊ฐ์ง ์ค์ํ ์ฃผ์ ์ฌํญ: WebAssembly ์ธ์คํด์ค๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฆฌ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋ฒํผ์ ๋ํ ๋ณด๊ธฐ๊ฐ ๋ฌดํจํ๋ฉ๋๋ค. WebAssembly ์ธ์คํด์ค์ ๋ํ ์ถ๊ฐ ํธ์ถ ์ดํ์ ์ง์๋๋ ๋ทฐ์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์ฅํ์ง ๋ง์ญ์์ค.
@binji ์ด๊ฒ์ ์ฌ์ฉํ ๋ AssemblyScript ์ธก์ ๋ฌด์์ ๋ฃ๋์ง ์๋ ค
let myWasmArrayPtr = instance.exports.allocateF32Array(length);
๋๋ ๋ค์๊ณผ ๊ฐ์ด ์ฐ๊ณ ์๋ํ์ง๋ง ์ฌ์ ํ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ธ์ง ์๊ณ ์ถ์ต๋๋ค.
export function allocateF32Array(length: usize): usize {
return memory.allocate(length * sizeof<f32>());
}
memory.free()
๋ก ํด์ ํ๋ ค๋ฉด ๋ค๋ฅธ AS ํจ์๋ฅผ ์์ฑํด์ผ ํ๊ณ ๋ฐฐ์ด์ JS ์ธก์ ์ ์กํ ํ ํธ์ถํด์ผ ํฉ๋๊น?
@fmkang @binji๊ฐ ์ค๋ช ํ ๋ด์ฉ์ JS ์ธก์์ ์ค๋ช ํ ๊ฒ์ ๋๋ค(ํ๋ฆฐ ๊ฒฝ์ฐ ์์ ํด ์ฃผ์ธ์).
Typed Arrays๋ฅผ ์ฌ์ฉํ๋ฉด Wasm Array Buffer์ ํจ๊ป set() ์ ์ฌ์ฉํ์ฌ JS ์ธก์์ WASM ๋ฉ๋ชจ๋ฆฌ์ ํจ์จ์ ์ผ๋ก ์ธ ์ ์์ต๋๋ค.
Wasm/AS ๋ด๋ถ์์ Wasm ๋ฉ๋ชจ๋ฆฌ์ ์ฐ๊ธฐ, ์ฌ์ ํ ํ์ค for ๋ฃจํ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค(์: https://github.com/torch2424/wasmBoy/blob/master/core/memory/dma.ts#L29).
ํ์ง๋ง @MaxGraey ๋๋ @dcodeIO ๊ฐ AS ๋๋ Wasm ๋๋ ๋ด๋ถ์์ ๊ฐ์ฅ ํจ์จ์ ์ผ๋ก ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋์์ด ๋ ์ ์์ต๋๊น? ๐ ๋น๋ก ์ด๊ฒ์ AS repo๋ก ์ฎ๊ธฐ๋ ๊ฒ์ด ๋ ๋์ ์๋ ์์ง๋ง
@fmkang ๋น์ ์ ๋จ์ํ
export function allocateF32Array(length: i32): Float32Array {
return new Float32Array(length);
}
AS ์ธก๊ณผ
let myArray = module.getArray(Float32Array, module.allocateF32Array(length));
JS ์ธก ์์ loader ๋ฅผ ์ฌ์ฉ
@torch2424 ์, @binji ์ ์ฝ๋๋ JS ์ชฝ์ ์์ง๋ง let myWasmArrayPtr = instance.exports.allocateF32Array(length)
๋ Wasm ๋ชจ๋์์ allocateF32Array
๋ผ๋ ํจ์๋ฅผ ํธ์ถํ๊ณ ์์ต๋๋ค(AssembleScript๋ก ์ปดํ์ผ๋์์ ๊ฐ๋ฅ์ฑ์ด ๋์). ์ด ๊ธฐ๋ฅ์ ๊ทธ์ ์ค๋ํซ์ด๋ AS ๋ด์ฅ ๊ธฐ๋ฅ์ ์ผ๋ถ์ ์ธ๊ธ๋์ด ์์ง ์์ผ๋ฏ๋ก ์ง์ ๊ตฌํํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋์ํ๋ Wasm ๋ฐฐ์ด์ ๊ฐ๋ฆฌํค๋ ์ด ํฌ์ธํฐ๋ฅผ ์ป๋ ๋ฐฉ๋ฒ์ ๋ฌป๊ณ ์์ต๋๋ค.
@dcodeIO ๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ์ ์ ๋ฌ ๋ฐฐ์ด์ ๋จ์ํํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ๊ธฐ์ ์๋ก์ด ์๊ฒฌ์ ๊ฒ์ํ๊ธฐ ์ ์ ์ ์คํ๊ฒ ์คํํด ๋ณด๊ฒ ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ด ๊ธฐ๋ฅ์ ๊ทํ์ ๊ธฐ๋ฅ์ผ๋ก ๊ต์ฒดํ ํ ๋ก๋๋ ๋ ๋ด ๋ชจ๋์ด ์ถฉ๋ํฉ๋๋ค. ์ฝ์์ ๋งํ๋ค
astest.html:1 Uncaught (in promise) TypeError: WebAssembly Instantiation: Import #0 module="env" error: module is not an object or function
๋ด AS ์ฝ๋์ ์๋ฌด ๊ณณ์๋ let a = new Float32Array(10);
์ ๊ฐ์ ๊ฒ์ ์ฐ๋ฉด ์ถฉ๋์ด ๋ฐ์ํฉ๋๋ค.
@dcodeIO ( let c: f64[] = [a[0] + b[0], a[1] + b[1]];
์ ๊ฐ์ ๋ฆฌํฐ๋ด ๋์ ) ํํ์์ ์ฌ์ฉํ์ฌ ๋ฐฐ์ด์ ์ด๊ธฐํํ๊ฑฐ๋ ๋ฐฐ์ด์ ์์์ ๊ฐ์ ํ ๋นํ๋ ค๊ณ ํ ๋(์: let a: f64[] = [0, 0, 0]; a[0] = 1;
๋๋ let array = new Array<i32>(); array.push(1);
) Wasm ๋ชจ๋์ด ์ถฉ๋ํฉ๋๋ค
์ฒ์์๋ memory
๋ฅผ env
๋ฃ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ์ต๋๋ค.
var importObject = {
env: { memory: new WebAssembly.Memory({initial:10}) },
imports: { imported_func: arg => console.log(arg) }
};
WebAssembly.instantiate(wasmBinary, importObject).then(...);
๊ทธ๋ฌ๋ ๋ฌธ์ ๋ ์ฌ์ ํ ์กด์ฌํ์ต๋๋ค. ๊ทธ๋ฌ๋ค๊ฐ abort
๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ผ๋ ๊ฒ์ ์๊ฒ ๋์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ด ์ผ์ต๋๋ค.
env: {
abort(msg, file, line, column) {
console.error("abort called at main.ts:" + line + ":" + column);
}
}
๋๋ ๋จ์ํ env: { abort: function(){} }
ํ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค๋ฅ ๋ฉ์์ง๊ฐ ์์ผ๋ฉฐ ์ฝ๋ ์คํ์ด ์ค์ ๋ก "์ค๋จ"๋์ง ์์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฌ์ ํ ์ด ๋ฌธ์ ์ ์ค์ ์์ธ์ ๋ชจ๋ฆ
๋๋ค.
์ฐ๋ฆฌ๋ WebAssembly๋ฅผ ์ฒ์ ์ ํฉ๋๋ค. ๋๋ ๋จ์ง ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด์ด ๊ฒ์๋ฌผ์ ์์ฑํฉ๋๋ค. ๋ต์ฅ์ ํ ํ์๋ ์์ต๋๋ค.
@fmkang ๋ชจ๋์ ์ธ์คํด์คํํ๊ธฐ ์ํด AssemblyScript ๋ก๋ ๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด ๋ชจ๋ ๊ฒ์ ์ง์ ๊ตฌํํ ์ ์์ง๋ง ๋ก๋๋ ์ด๋ฏธ ์ค๋จ ๊ธฐ๋ฅ๊ณผ ๊ฐ์ ๋ชจ๋ ๋ด๋ณด๋ด๊ธฐ์ ๋ํ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ์ถ๊ฐํฉ๋๋ค. AssemblyScript์ ๋ํด ๋ ๊ถ๊ธํ ์ฌํญ์ด ์๋ ๊ฒฝ์ฐ ๋ฌธ์ ์ถ์ ๊ธฐ ์ ๋ฌธ์ํด ์ฃผ์๋ฉด ๊ธฐ๊บผ์ด ๋์๋๋ฆฌ๊ฒ ์ต๋๋ค. :)
๊ทธ๋์ ์ด ๊ธฐ์ ์ ์ฌ์ฉํด ๋ณด์์ต๋๋ค.
let myArrayPtr = instance.exports.allocateF32Array(length);
let myArray = new Float32Array(instance.exports.memory.buffer, myArrayPtr, length);
// Use myArray as a normal Float32Array in JavaScript, fill in data, etc.
...
// Process the data in the array.
instance.exports.processF32Array(myArrayPtr, length);
๊ทธ๋ฌ๋ ๋ด processF32Array ํจ์ ๊ฒฐ๊ณผ๋ RuntimeError: memory access out of bounds
์
๋๋ค. ๋๋ ๋ก๋, FWIW๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค. ๋๋ ๋ํ ์๋ํ๋ค :
let myArray = module.getArray(Float32Array, module.allocateF32Array(length));
๊ทธ๋ฌ๋ ๋ด ๋ชจ๋์๋ "getArray"๊ฐ ์์ผ๋ฉฐ ์ด๋ป๊ฒ ๊ฐ์ ธ์์ผ ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
WebAssembly๋ก/์์ ๋ฐฐ์ด์ ๋ณต์ฌํ๋ ๋ฐฉ๋ฒ์ ์ฐพ๊ณ ์์๋๋ฐ ์ด ์ค๋ ๋๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค. ๋ค๋ฅธ ์ฌ๋์ ๊ฒฝ์ฐ AssemblyScript ๋ฐ @torch2424 ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ as-bind ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฐ์ด์ ๋ณต์ฌํ ์ ์์์ต๋๋ค.
๋ด ๊ฐ๋จํ ํ ์คํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด์ ๋ธ๋ฆฌ์คํฌ๋ฆฝํธ
export function sum(arr: Float64Array): f64 {
let sum: f64 = 0;
for(let i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
์๋ฐ์คํฌ๋ฆฝํธ(๋ ธ๋)
const { AsBind } = require("as-bind");
const fs = require("fs");
const wasm = fs.readFileSync(__dirname + "/build/optimized.wasm");
const asyncTask = async () => {
const asb = await AsBind.instantiate(wasm);
// Make a large array
console.time('Making array');
let arr = new Float64Array(1e8).fill(1);
console.timeEnd('Making array');
// Find the sum using reduce
console.time('Reduce');
let sum1 = arr.reduce((acc, val) => acc + val, 0);
console.timeEnd('Reduce');
// Find the sum with for loops
console.time('JS For');
let sum2 = 0;
for(let i = 0; i < arr.length; i++) sum2 += arr[i];
console.timeEnd('JS For');
// Find the sum with WebAssembly
console.time('Wasm For');
let sum3 = asb.exports.sum(arr);
console.timeEnd('Wasm For');
console.log(sum1, sum2, sum3);
};
asyncTask();
๋ด ์ปดํจํฐ์์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์์ต๋๋ค.
Making array: 789.086ms
Reduce: 2452.922ms
JS For: 184.818ms
Wasm For: 2008.482ms
100000000 100000000 100000000
์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ฐฐ์ด์ WebAssembly๋ก ๋ณต์ฌํ ๋ ์๋นํ ์ค๋ฒํค๋๊ฐ ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ํฉ๊ณ๋ณด๋ค ๋ ๋น์ผ ์์ ์ ๋ํด ์ ์ถฉ์ด ๊ฐ์น๊ฐ ์๋ค๊ณ ์์ํ ์ ์์ต๋๋ค.
ํธ์งํ๋ค:
๋ฐฐ์ด ๋ณต์ฌ๋ณธ์ ์คํ ์๊ฐ์ ๋ถ๋ฆฌํ๊ธฐ ์ํด AssemblyScript์์ ํฉ๊ณ๋ฅผ ์ ๊ฑฐํ์ต๋๋ค.
export function sum(arr: Float64Array): f64 {
let sum: f64 = 0;
return sum;
}
๊ทธ๋ฆฌ๊ณ ๋ฒค์น๋งํฌ๋ฅผ ๋ค์ ์คํํ์ต๋๋ค.
Wasm ํฉ๊ณ ์์
Making array: 599.826ms
Reduce: 2810.395ms
JS For: 188.623ms
Wasm For: 762.481ms
100000000 100000000 0
๋ฐ๋ผ์ ๋ฐ์ดํฐ ๋ณต์ฌ ์์ฒด๊ฐ 1์ต f64
s ์ด์์ ๋ณต์ฌํ๋ ๋ฐ 762.481ms๊ฐ ๊ฑธ๋ฆฐ ๊ฒ ๊ฐ์ต๋๋ค.
@pwstegman ๋ฌด์์ ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ณ js ์์ง์ด ๋ฃจํ๋ฅผ ์ต์ ํํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋ ๋ค๋ฅธ ๋ฒค์น๋งํฌ๋ฅผ ๋ง๋ค์์ต๋๋ค. https://webassembly.studio/?f=5ux4ymi345e
Chrome ๋ฐ FF์ ๊ฒฝ์ฐ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฆ ๋๋ค.
Chrome 81.0.4044.129
js sum: 129.968017578125ms
sum result = 49996811.62100115
js reduce: 1436.532958984375ms
js reduce result = 49996811.62100115
wasm sum: 153.000244140625ms
wasm sum result = 49996811.62100115
wasm reduce: 125.009033203125ms
wasm reduce result = 49996811.62100115
wasm empty: 0.002685546875ms
์๋
ํ์ธ์.
์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก WASM์ ๋ํ ์น์ํจ๊ณผ ๊ด๋ จํ์ฌ ์ ์์์ด๋ฉฐ ์ฌ๊ธฐ์ #1162์ ์๋ ์ฌ๋๋ค๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์ฐ์ฐํ ๋ฐ๊ฒฌํ์ต๋๋ค. (์ด๊ฒ์ด ๋ ์ต๊ทผ ํ๋์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋ ์ฌ๊ธฐ์ #1162 ๋๋ฅผ ๋ฌป๋๋ค.)
๊ฐ๋จํ ์ฐ๊ตฌ ํ ๋๋ ๊ทธ๊ฒ์ ์์ ๋ด๋ ค๊ณ ์๋ํ๋ฉด์ ๋ฐ๋ชจ ๋ฅผ ๋ง๋ค์๊ณ ๋ฐ์ดํฐ ๋ณต์ฌ๋ฅผ ํผํ๊ธฐ ์ํด ์ ํ์ด ์ง์ ๋ ๋ฐฐ์ด๋ก WASM ๋ฉ๋ชจ๋ฆฌ์ ๋ทฐ๋ฅผ ๋
ธ์ถํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋๋ฌ์ต๋๋ค. ์ฌ๊ธฐ JS ๊ด์ ์์ ์์ ์ด ์์ต๋๋ค. :
// need to know the size in advance, that's OK since the impl makes some init
const fft = new Module.KissFftReal(/*size=*/N);depending on the size anyway
// get view into WASM memory as Float64Array (of size=N in this case)
const input = fft.getInputTimeDataBuffer();
// fill 'input' buffer
// perform transformation, view into WASM memory is returned here (of size=(N + 2) in this case, +2 for Nyquist bin)
const output = fft.transform();
// use transformation result returned in 'output' buffer
์ด๊ฒ์ด ๊ฐ ๊ธธ์ธ๊ฐ? ๋ ๋์ ์๋ฃจ์ ์ด ์์ต๋๊น? ์ด ์ฃผ์ ์ ๋ํ ๋ชจ๋ ์๊ฒฌ/์๋ก ๊ณ ์นจ์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
์ถ์ ๋น๋ก ์ถ์ ํ์ง๋ง ๊ทธ๊ฒ์ ์ค์ ๋ก ๋๋ฅผ ์ํด ํ์์ ์ผ๋ก ์๋ํฉ๋๋ค (๋ด๊ฐ ๊ทธ๊ฒ์ ์ดํดํ๊ณ ๊ฐ์ฌํ ์ ์๋ ํ)
pps
๋ค์์ ์ ์ฌํ ๋ฌธ์ ์ ๊ดํ ๋ด (์์ง ๋ต๋ณ๋์ง ์์) stackoverflow ์ง๋ฌธ์
๋๋ค.
https://stackoverflow.com/questions/65566923/is-there-a-more-efficient-way-to-return-arrays-from-c-to-javascript
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
JavaScript์ WebAssembly ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ ์ง ์๋๋ฉด WebAssembly๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋๋ก ํ ์ง ๊ฒฐ์ ํด์ผ ํฉ๋๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๋ ค๋ฉด
for
๋ฃจํ๋ฅผ ์ง์ ์์ฑํ๋ ๋์ TypedArray.prototype.set() ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.WebAssembly๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ
WebAssembly.Memory
๋ฒํผ์ ๋ํ ๋ณด๊ธฐ๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ JavaScript ํจ์์๋ ์ ๋ฌํ ์ ์์ต๋๋ค.๋ํ embind ์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ข ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.