Skip to content

Commit fe6bbef

Browse files
committed
Merge ml/tensor-ops-d-bmm-int: batched matmul + integer/bit ops (ops D)
# Conflicts: # crates/rsscript/src/reg_vm/mod.rs # crates/rsscript/src/runtime_abi.rs # crates/rsscript/tests/vm_eval.rs # crates/rsscript/tests/vm_eval_parity/tensor.rs # crates/runtime/src/tensor.rs # packages/ml/interface/tensor.rssi
2 parents bfa699e + 3560edc commit fe6bbef

6 files changed

Lines changed: 535 additions & 0 deletions

File tree

crates/rsscript/src/reg_vm/mod.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,6 +2126,17 @@ enum RegIntrinsic {
21262126
TensorLog2,
21272127
TensorRsqrt,
21282128
TensorPow,
2129+
// bmm+int/bit (ops D)
2130+
TensorBmm,
2131+
TensorIdiv,
2132+
TensorMod,
2133+
TensorShl,
2134+
TensorShr,
2135+
TensorAnd,
2136+
TensorOr,
2137+
TensorXor,
2138+
TensorBitcastF32ToI32,
2139+
TensorBitcastI32ToF32,
21292140
TensorErrorMessage,
21302141
CharCompare,
21312142
CharFromCode,
@@ -5411,6 +5422,17 @@ fn qualified_intrinsic(namespace: &str, name: &str) -> Option<RegIntrinsic> {
54115422
("Tensor", "log2") => Some(RegIntrinsic::TensorLog2),
54125423
("Tensor", "rsqrt") => Some(RegIntrinsic::TensorRsqrt),
54135424
("Tensor", "pow") => Some(RegIntrinsic::TensorPow),
5425+
// bmm+int/bit (ops D)
5426+
("Tensor", "bmm") => Some(RegIntrinsic::TensorBmm),
5427+
("Tensor", "idiv") => Some(RegIntrinsic::TensorIdiv),
5428+
("Tensor", "modulo") => Some(RegIntrinsic::TensorMod),
5429+
("Tensor", "shl") => Some(RegIntrinsic::TensorShl),
5430+
("Tensor", "shr") => Some(RegIntrinsic::TensorShr),
5431+
("Tensor", "bit_and") => Some(RegIntrinsic::TensorAnd),
5432+
("Tensor", "bit_or") => Some(RegIntrinsic::TensorOr),
5433+
("Tensor", "bit_xor") => Some(RegIntrinsic::TensorXor),
5434+
("Tensor", "bitcast_f32_to_i32") => Some(RegIntrinsic::TensorBitcastF32ToI32),
5435+
("Tensor", "bitcast_i32_to_f32") => Some(RegIntrinsic::TensorBitcastI32ToF32),
54145436
("TensorError", "message") => Some(RegIntrinsic::TensorErrorMessage),
54155437
("Char", "compare") => Some(RegIntrinsic::CharCompare),
54165438
("Char", "from_code") => Some(RegIntrinsic::CharFromCode),
@@ -9594,6 +9616,44 @@ impl RegVm {
95949616
)),
95959617
}))
95969618
}
9619+
// bmm+int/bit (ops D)
9620+
RegIntrinsic::TensorBmm
9621+
| RegIntrinsic::TensorIdiv
9622+
| RegIntrinsic::TensorMod
9623+
| RegIntrinsic::TensorShl
9624+
| RegIntrinsic::TensorShr
9625+
| RegIntrinsic::TensorAnd
9626+
| RegIntrinsic::TensorOr
9627+
| RegIntrinsic::TensorXor => {
9628+
let a = self.expect_tensor_ref(intrinsic_arg(&self.stack, base, args, 0)?)?;
9629+
let b = self.expect_tensor_ref(intrinsic_arg(&self.stack, base, args, 1)?)?;
9630+
let result = match intrinsic {
9631+
RegIntrinsic::TensorBmm => rsscript_runtime::tensor_bmm(&a, &b),
9632+
RegIntrinsic::TensorIdiv => rsscript_runtime::tensor_idiv(&a, &b),
9633+
RegIntrinsic::TensorMod => rsscript_runtime::tensor_mod(&a, &b),
9634+
RegIntrinsic::TensorShl => rsscript_runtime::tensor_shl(&a, &b),
9635+
RegIntrinsic::TensorShr => rsscript_runtime::tensor_shr(&a, &b),
9636+
RegIntrinsic::TensorAnd => rsscript_runtime::tensor_and(&a, &b),
9637+
RegIntrinsic::TensorOr => rsscript_runtime::tensor_or(&a, &b),
9638+
_ => rsscript_runtime::tensor_xor(&a, &b),
9639+
};
9640+
Ok(json_result(match result {
9641+
Ok(tensor) => Ok(self.store_tensor(tensor)),
9642+
Err(error) => Err(tensor_error_value(
9643+
rsscript_runtime::tensor_error_message(&error),
9644+
)),
9645+
}))
9646+
}
9647+
RegIntrinsic::TensorBitcastF32ToI32 | RegIntrinsic::TensorBitcastI32ToF32 => {
9648+
let t = self.expect_tensor_ref(intrinsic_arg(&self.stack, base, args, 0)?)?;
9649+
let result = match intrinsic {
9650+
RegIntrinsic::TensorBitcastF32ToI32 => {
9651+
rsscript_runtime::tensor_bitcast_f32_to_i32(&t)
9652+
}
9653+
_ => rsscript_runtime::tensor_bitcast_i32_to_f32(&t),
9654+
};
9655+
Ok(self.store_tensor(result))
9656+
}
95979657
RegIntrinsic::CharCompare | RegIntrinsic::CharFromCode | RegIntrinsic::CharIsAlphanumeric | RegIntrinsic::CharIsAlpha | RegIntrinsic::CharIsDigit | RegIntrinsic::CharIsLower | RegIntrinsic::CharIsUpper | RegIntrinsic::CharIsWhitespace | RegIntrinsic::CharToCode | RegIntrinsic::CharToLower | RegIntrinsic::CharToString | RegIntrinsic::CharToUpper => self.exec_char_intrinsics(unit, intrinsic, args, base, next_base),
95989658
RegIntrinsic::ClockNow => Ok(instant_value(clock_system_unix_ms())),
95999659
RegIntrinsic::ClockSystemUnixMs => Ok(VmValue::Int(clock_system_unix_ms())),

crates/rsscript/src/runtime_abi.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,25 @@ const RUNTIME_INTRINSICS: &[RuntimeIntrinsic] = &[
494494
runtime_intrinsic("Tensor", "log2", "rsscript_runtime::tensor_log2"),
495495
runtime_intrinsic("Tensor", "rsqrt", "rsscript_runtime::tensor_rsqrt"),
496496
runtime_intrinsic("Tensor", "pow", "rsscript_runtime::tensor_pow"),
497+
// bmm+int/bit (ops D)
498+
runtime_intrinsic("Tensor", "bmm", "rsscript_runtime::tensor_bmm"),
499+
runtime_intrinsic("Tensor", "idiv", "rsscript_runtime::tensor_idiv"),
500+
runtime_intrinsic("Tensor", "modulo", "rsscript_runtime::tensor_mod"),
501+
runtime_intrinsic("Tensor", "shl", "rsscript_runtime::tensor_shl"),
502+
runtime_intrinsic("Tensor", "shr", "rsscript_runtime::tensor_shr"),
503+
runtime_intrinsic("Tensor", "bit_and", "rsscript_runtime::tensor_and"),
504+
runtime_intrinsic("Tensor", "bit_or", "rsscript_runtime::tensor_or"),
505+
runtime_intrinsic("Tensor", "bit_xor", "rsscript_runtime::tensor_xor"),
506+
runtime_intrinsic(
507+
"Tensor",
508+
"bitcast_f32_to_i32",
509+
"rsscript_runtime::tensor_bitcast_f32_to_i32",
510+
),
511+
runtime_intrinsic(
512+
"Tensor",
513+
"bitcast_i32_to_f32",
514+
"rsscript_runtime::tensor_bitcast_i32_to_f32",
515+
),
497516
runtime_intrinsic(
498517
"TensorError",
499518
"message",

crates/rsscript/tests/vm_eval.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,7 @@ pub fn echo(message: &String) -> String {
10751075
// parity: runtime:Tensor.cast_f32 runtime:Tensor.cast_i32 runtime:Tensor.cast_bool runtime:Tensor.dtype_code
10761076
// parity: runtime:Tensor.pad runtime:Tensor.shrink runtime:Tensor.flip runtime:Tensor.gather
10771077
// parity: runtime:Tensor.prod_axis runtime:Tensor.min_axis runtime:Tensor.sum_axes runtime:Tensor.prod_axes runtime:Tensor.max_axes runtime:Tensor.min_axes runtime:Tensor.mean_axes runtime:Tensor.reciprocal runtime:Tensor.exp2 runtime:Tensor.log2 runtime:Tensor.rsqrt runtime:Tensor.pow
1078+
// parity: runtime:Tensor.bmm runtime:Tensor.idiv runtime:Tensor.modulo runtime:Tensor.shl runtime:Tensor.shr runtime:Tensor.bit_and runtime:Tensor.bit_or runtime:Tensor.bit_xor runtime:Tensor.bitcast_f32_to_i32 runtime:Tensor.bitcast_i32_to_f32
10781079
// parity: runtime:Timer.sleep runtime:Timer.sleep_cancellable runtime:Timer.sleep_until
10791080
// parity: runtime:Tcp.connect runtime:TcpError.message
10801081
// parity: runtime:TcpStream.read runtime:TcpStream.shutdown

crates/rsscript/tests/vm_eval_parity/tensor.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,3 +1285,96 @@ fn main() -> Result<Unit, TensorError> {
12851285
source,
12861286
);
12871287
}
1288+
1289+
// bmm+int/bit (ops D)
1290+
1291+
#[test]
1292+
fn parity_tensor_bmm() {
1293+
let source = r#"
1294+
features: native, local
1295+
1296+
fn dump(t: read Tensor) -> Result<Unit, TensorError> {
1297+
let shape = Tensor.shape(tensor: read t)?
1298+
let mut si = 0
1299+
while si < List.len(list: read shape) {
1300+
Log.write(message: read String.from_int(value: List.get(list: read shape, index: si)))
1301+
si = si + 1
1302+
}
1303+
let values = Tensor.to_f32_slice(tensor: read t)?
1304+
let mut index = 0
1305+
while index < List.len(list: read values) {
1306+
Log.write(message: read Float.to_string(value: read List.get(list: read values, index: index)))
1307+
index = index + 1
1308+
}
1309+
return Ok(Unit)
1310+
}
1311+
1312+
fn main() -> Result<Unit, TensorError> {
1313+
let a = Tensor.from_f32_slice(data: read [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], shape: read [2, 2, 2])?
1314+
let b = Tensor.from_f32_slice(data: read [1.0, 0.0, 0.0, 1.0, 2.0, 0.0, 0.0, 2.0], shape: read [2, 2, 2])?
1315+
let c = Tensor.bmm(a: read a, b: read b)?
1316+
dump(t: read c)?
1317+
// Broadcast a single matrix over the batch dim.
1318+
let big = Tensor.from_f32_slice(data: read [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0], shape: read [2, 2, 3])?
1319+
let w = Tensor.from_f32_slice(data: read [1.0, 0.0, 0.0, 1.0, 1.0, 1.0], shape: read [1, 3, 2])?
1320+
let bc = Tensor.bmm(a: read big, b: read w)?
1321+
dump(t: read bc)?
1322+
return Ok(Unit)
1323+
}
1324+
"#;
1325+
common::assert_vm_eval_matches_backend(
1326+
"parity-tensor-bmm.rss",
1327+
"rsscript_parity_tensor_bmm",
1328+
source,
1329+
);
1330+
}
1331+
1332+
#[test]
1333+
fn parity_tensor_int_bit_ops() {
1334+
let source = r#"
1335+
features: native, local
1336+
1337+
fn dump(t: read Tensor) -> Result<Unit, TensorError> {
1338+
Log.write(message: read String.from_int(value: Tensor.dtype_code(t: read t)))
1339+
let values = Tensor.to_f32_slice(tensor: read t)?
1340+
let mut index = 0
1341+
while index < List.len(list: read values) {
1342+
Log.write(message: read Float.to_string(value: read List.get(list: read values, index: index)))
1343+
index = index + 1
1344+
}
1345+
return Ok(Unit)
1346+
}
1347+
1348+
fn main() -> Result<Unit, TensorError> {
1349+
let af = Tensor.from_f32_slice(data: read [7.0, -7.0, 12.0, 6.0], shape: read [4])?
1350+
let bf = Tensor.from_f32_slice(data: read [2.0, 2.0, 3.0, 0.0], shape: read [4])?
1351+
let a = Tensor.cast_i32(t: read af)
1352+
let b = Tensor.cast_i32(t: read bf)
1353+
let q = Tensor.idiv(a: read a, b: read b)?
1354+
dump(t: read q)?
1355+
let r = Tensor.modulo(a: read a, b: read b)?
1356+
dump(t: read r)?
1357+
let shf = Tensor.from_f32_slice(data: read [1.0, 2.0, 1.0, 2.0], shape: read [4])?
1358+
let sh = Tensor.cast_i32(t: read shf)
1359+
let l = Tensor.shl(a: read a, b: read sh)?
1360+
dump(t: read l)?
1361+
let rs = Tensor.shr(a: read a, b: read sh)?
1362+
dump(t: read rs)?
1363+
let aa = Tensor.bit_and(a: read a, b: read b)?
1364+
dump(t: read aa)?
1365+
let oo = Tensor.bit_or(a: read a, b: read b)?
1366+
dump(t: read oo)?
1367+
let xx = Tensor.bit_xor(a: read a, b: read b)?
1368+
dump(t: read xx)?
1369+
let bits = Tensor.bitcast_f32_to_i32(t: read af)
1370+
let back = Tensor.bitcast_i32_to_f32(t: read bits)
1371+
dump(t: read back)?
1372+
return Ok(Unit)
1373+
}
1374+
"#;
1375+
common::assert_vm_eval_matches_backend(
1376+
"parity-tensor-int-bit-ops.rss",
1377+
"rsscript_parity_tensor_int_bit_ops",
1378+
source,
1379+
);
1380+
}

0 commit comments

Comments
 (0)