Assemblyscript: u16 / u32 / f64を共有する方法...メモリに影響しますか?

作成日 2018年12月12日  ·  4コメント  ·  ソース: AssemblyScript/assemblyscript

ASとJSからメモリにアクセスするには、 MDNExampleのようなコードを使用します。
しかし、u8 / i8を除いて、すべてのテストパターンが失敗し、JSで表示されたデータがASで表示されたデータとは異なることがわかりました。

データをfloatに格納するにはどうすればよいですか?

私のコードは次のようになります:

`` `index.ts
// assembly / index.ts

エクスポート関数readMemoryU8(オフセット:usize):u8 {
戻り荷重(オフセット)
}

エクスポート関数writeMemoryU8(オフセット:usize、値:u8):void {
お店(オフセット、値)
}

エクスポート関数readMemoryU16(オフセット:usize):u16 {
戻り荷重(オフセット)
}

エクスポート関数writeMemoryU16(オフセット:usize、値:u16):void {
お店(オフセット、値)
}

エクスポート関数readMemoryF64(オフセット:usize):f64 {
戻り荷重(オフセット)
}

エクスポート関数writeMemoryF64(オフセット:usize、値:f64):void {
お店(オフセット、値)
}

//..。

```index.js
// index.js

const fs = require("fs");
const compiled = new WebAssembly.Module(fs.readFileSync(__dirname + "/build/optimized.wasm"));
const imports = {};
Object.defineProperty(module, "exports", {
  get: () => new WebAssembly.Instance(compiled, imports).exports
});

`` `index.test.js
// __tests __ / index.test.js

const wasm = require( '../ index');
const memory = wasm.memory;

describe( 'Test WASM'、()=> {
beforeAll(()=> {
const mem = new Uint8Array(memory.buffer);
if(mem.length <1){
memory.grow(1);
}
wasm.memory.grow(1);
});

test( '読み取り/書き込みuint8'、()=> {
const mem = new Uint8Array(memory.buffer);

mem.set([1, 3, 5]);
console.log([0, 1, 2, 3, 4, 5].map(wasm.readMemoryU8));
// [ 1, 3, 5, 0, 0, 0 ]
console.log(mem.subarray(0, 6));
//Uint8Array [ 1, 3, 5, 0, 0, 0 ]
expect(wasm.readMemoryU8(1)).toBe(3);
wasm.writeMemoryU8(1, 6);
expect(wasm.readMemoryU8(1)).toBe(6);
expect(mem[1]).toBe(6);
expect(wasm.readMemoryU8(0)).toBe(1);
expect(wasm.readMemoryU8(2)).toBe(5);

});

test( '読み取り/書き込みuint16'、()=> {
const mem = new Uint16Array(memory.buffer);

mem.set([1, 3, 257]);
console.log([0, 1, 2, 3, 4, 5].map(wasm.readMemoryU16)); 
// [ 1, 768, 3, 256, 257 ]
console.log(mem.subarray(0, 6)); 
// Uint16Array [ 1, 3, 257, 0, 0, 0 ]
expect(wasm.readMemoryU16(0)).toBe(1);
expect(wasm.readMemoryU16(1)).toBe(3); // failed
wasm.writeMemoryU16(1, 6);
expect(wasm.readMemoryU16(1)).toBe(6);
expect(mem[1]).toBe(6);
expect(wasm.readMemoryU16(2)).toBe(5);

});

test( 'read / write float64'、()=> {
const mem = new Float64Array(memory.buffer);

mem.set([1, -3.2, 25.8]);

console.log([0, 1, 2, 3, 4, 5].map(wasm.readMemoryF64));
// [ 1,
//  -3.0065162379579438e-182,
//  -2.413170169815393e-185,
//  -2.3536706995205933e-185,
//  -2.3534382797147542e-185,
//  -2.3534373718248877e-185 ]
console.log(mem.subarray(0, 6));
// Float64Array [ 1, -3.2, 25.8, 0, 0, 0 ]
expect(wasm.readMemoryF64(0)).toBe(1);
expect(wasm.readMemoryF64(1)).toBe(-3.2); // failed
wasm.writeMemoryI16(1, -6.5);
expect(wasm.readMemoryF64(1)).toBe(-6.5);
expect(mem[1]).toBe(-6.5);
expect(wasm.readMemoryI16(2)).toBe(25.8);

});
});

`` `

最も参考になるコメント

あなたの場合のoffsetは正確なメモリ位置ですが、乗算する必要があるインデックスを渡しています。 f64を使用する場合は、オフセットを8バイト(これは64ビット値)ずつインクリメントして、値が互いに上書きされないようにする必要があります。

export function readMemoryF64(index: u32): f64 {
  return load<f64>(index << alignof<f64>());
}

export function writeMemoryF64(index: u32, value: f64): void {
  store<f64>(index << alignof<f64>(), value);
}

全てのコメント4件

増分はオフセットの場合は常に1のように見えます。これは、8ビット値の場合は正しいですが、16ビット値の場合は2 $、32ビット値の場合4である必要があります。など、ここでは値が互いに上書きする状況になります。

@dcodeIO
それがまさに問題です。 store<f64>(0, 1.5)の場合、次にstore<f64>(1, 2.7) 、この場合、 load<f64>(0)は奇妙な値を返します。 ただし、 load<f64>(1)2.7 $を返します。

あなたの場合のoffsetは正確なメモリ位置ですが、乗算する必要があるインデックスを渡しています。 f64を使用する場合は、オフセットを8バイト(これは64ビット値)ずつインクリメントして、値が互いに上書きされないようにする必要があります。

export function readMemoryF64(index: u32): f64 {
  return load<f64>(index << alignof<f64>());
}

export function writeMemoryF64(index: u32, value: f64): void {
  store<f64>(index << alignof<f64>(), value);
}

@dcodeIO
テストに合格しました!
どうもありがとう!

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

blooddy picture blooddy  ·  3コメント

torch2424 picture torch2424  ·  5コメント

DanielMazurkiewicz picture DanielMazurkiewicz  ·  4コメント

kungfooman picture kungfooman  ·  5コメント

MaxGraey picture MaxGraey  ·  4コメント