mod fixture;
use mircuda::{DeviceBuffer, DeviceElement, bf16};
use super::super::*;
use crate::{CudaConfig, Result};
#[test]
fn executes_affine_shared_and_routed_experts_for_prefill_and_decode() -> Result<()> {
let backend = CudaBackend::new(CudaConfig::default())?;
let config = config();
let fixture = fixture::MoeFixture::new(config)?;
let tensors = fixture.upload(&backend)?;
let moe = CudaAffineSharedExpertMoe::from_tensors(&backend, &tensors, fixture::PREFIX, config)?;
let input = copy(&backend, &vec![bf16::ZERO; 2 * config.hidden_size])?;
let mut output = allocate(&backend, 2 * config.hidden_size)?;
moe.prepare(2)?.execute(&input, &mut output)?;
assert!(read(&backend, &output)?.iter().all(|value| *value == bf16::ZERO));
let input = copy(&backend, &vec![bf16::ZERO; config.hidden_size])?;
let mut output = allocate(&backend, config.hidden_size)?;
moe.prepare(1)?.execute(&input, &mut output)?;
assert!(read(&backend, &output)?.iter().all(|value| *value == bf16::ZERO));
Ok(())
}
fn config() -> AffineSharedExpertMoeConfig {
AffineSharedExpertMoeConfig {
hidden_size: 64,
routed_intermediate_size: 64,
shared_intermediate_size: 64,
expert_count: 3,
top_k: 2,
group_size: 64,
expert_bits: 4,
router_bits: 8,
activation: GatedActivation::Silu,
}
}
fn allocate(backend: &CudaBackend, elements: usize) -> Result<DeviceBuffer<bf16>> {
Ok(backend.inner.pool.allocate(&backend.inner.stream, elements)?)
}
fn copy<T: DeviceElement>(backend: &CudaBackend, values: &[T]) -> Result<DeviceBuffer<T>> {
let mut host = backend.inner.context.allocate_pinned(values.len())?;
host.copy_from_slice(values)?;
let mut device = backend.inner.pool.allocate(&backend.inner.stream, values.len())?;
backend.inner.stream.copy_to_device(&mut host, &mut device)?;
Ok(device)
}
fn read<T: DeviceElement>(backend: &CudaBackend, source: &DeviceBuffer<T>) -> Result<Vec<T>> {
let mut host = backend.inner.context.allocate_pinned(source.len())?;
backend.inner.stream.copy_to_host(source, &mut host)?;
Ok(host.to_vec()?)
}