sea

O-CPS +AVX2

$ cat ./cargo/config

[target.x86_64-unknown-linux-gnu]
rustflags="-C target-feature=+avx,+avx2"

$ cargo build --release

$ objdump ./target/release/o -d | grep mulpd
   223f1:   c5 f5 59 0c d3          vmulpd (%rbx,%rdx,8),%ymm1,%ymm1
   223f6:   c5 dd 59 64 d3 20       vmulpd 0x20(%rbx,%rdx,8),%ymm4,%ymm4
   22416:   c5 f5 59 4c d3 40       vmulpd 0x40(%rbx,%rdx,8),%ymm1,%ymm1
   2241c:   c5 dd 59 64 d3 60       vmulpd 0x60(%rbx,%rdx,8),%ymm4,%ymm4
   2264d:   c5 f5 59 0c d3          vmulpd (%rbx,%rdx,8),%ymm1,%ymm1
   22652:   c5 e5 59 5c d3 20       vmulpd 0x20(%rbx,%rdx,8),%ymm3,%ymm3
$ objdump ./target/release/o -d | grep vpmul
   2251c:   c5 d5 f4 fb             vpmuludq %ymm3,%ymm5,%ymm7
   22525:   c4 41 55 f4 c0          vpmuludq %ymm8,%ymm5,%ymm8
   2253a:   c5 d5 f4 db             vpmuludq %ymm3,%ymm5,%ymm3
   22547:   c5 cd f4 ec             vpmuludq %ymm4,%ymm6,%ymm5
   22550:   c5 cd f4 ff             vpmuludq %ymm7,%ymm6,%ymm7
   22562:   c5 cd f4 e4             vpmuludq %ymm4,%ymm6,%ymm4
   22595:   c5 d5 f4 fb             vpmuludq %ymm3,%ymm5,%ymm7

$ rlwrap ./target/release/o
Welcome to O language interpreter 1.1.0
o)(1;2;3)*(2;3;4)
Instructions: 3
Conts: 2
ASTs: 26
ENV: (1,6)
End(Node(Value(VecInt([2, 6, 12]))))
Buy for 500 tokens
Buy promo for minimal price.
sea

Zero-Copy FlatMap комбинатор

В нашей системе по пасспорту сабж. Это значит что лейаут в память сделан таким образом, что итератор по FlatMap a точно такой же как по a. Т.е. комбинатор FlatMap = Id. А также это можно трансмьютить как слайс.

А как хранятся тензоры в ваших J?
sea

Pony vs O-CPS

Уважаемый thedeemon предложил обратить свой взор на pony lang.

$ cat main.pony 
use "time"
actor Main
  fun factorial(x: I64): I64 =>
  if x == 0 then
    1
  else
    x * factorial(x - 1)
  end
  fun ack(m: I64, n: I64): I64 =>
    if m == 0 then
        n + 1
    else if n == 0 then
        ack(m - 1, 1)
    else
        ack(m - 1, ack(m, n - 1))
    end end
  new create(env: Env) =>
    let axs: U64 = Time.nanos()
    let a: I64 = ack(3,4)
    let axe: U64 = Time.nanos()
    let fs: U64 = Time.nanos()
    let f: I64 = factorial(5)
    let fe: U64 = Time.nanos()
    let fac: U64 = fe - fs
    let akk: U64 = axe - axs
    env.out.print("Ackerman: " + fac.string() + "ns, " + a.string())
    env.out.print("Factorial: " +akk.string() + "ns, " + f.string())

$ ponyc
$ ./voxoz
Ackerman: 80332ns, 125
Factorial: 291ns, 120


В то время как у нас:

#[bench]
fn fac_rec<'a>(b: &'a mut Bencher) {
    let h = handle::new(Interpreter::new().unwrap());
    let eval = &"fac:{$[x=1;1;x*fac[x-1]]}".to_string();
    let mut code = h.borrow_mut().parse(eval);
    h.borrow_mut().run(code).unwrap();
    let f = h.borrow_mut().parse(&"fac[5]".to_string());
    b.iter(|| {
        h.borrow_mut().run(f);
        h.borrow_mut().gc();
    })
}

#[bench]
fn akkerman_k<'a>(b: &'a mut Bencher) {
    let h = handle::new(Interpreter::new().unwrap());
    h.borrow_mut().define_primitives();
    let akk = h.borrow_mut().parse(&"f:{[x;y]$[0=x;1+y;$[0=y;f[x-1;1];f[x-1;f[x;y-1]]]]}".to_string());
    h.borrow_mut().run(akk).unwrap();
    let call = h.borrow_mut().parse(&"f[3;4]".to_string());
    b.iter(|| {
        h.borrow_mut().run(call);
        h.borrow_mut().gc();
    })
}


test akkerman_k        ... bench:         442 ns/iter (+/- 37)
test fac_rec           ... bench:         195 ns/iter (+/- 55)
sea

Генерация AVX mm256_mul_pd

#![feature(target_feature)]

// $ rustc -C opt-level=3 --emit asm intint.rs
// $ cat intint.s | grep mul

#[target_feature = "+avx"]
pub fn mul_array_float<'a>(x: &mut[f64], y: &[f64]) {
    let n: Vec = x.iter().zip(y).map(|(d,c)|d*c).collect();
    println!("{:?}",n);
}

#[target_feature = "+avx"]
pub fn mul_array<'a>(x: &mut [u64], y: &[u64]) {
    let n: Vec = x.iter().zip(y).map(|(d,c)|d*c).collect();
    println!("{:?}",n);
}

fn main() {
    let mut fa = vec![0.0, 1.0, 4.0, 9.0, 0.0, 1.0, 4.0, 9.0, 0.0, 1.0, 4.0, 9.0, 0.0, 1.0, 4.0, 9.0];
    let fb     = vec![0.0, 2.0, 6.0, 0.0, 0.0, 1.0, 4.0, 9.0, 0.0, 2.0, 6.0, 0.0, 0.0, 1.0, 4.0, 9.0];
    let mut a  = vec![0, 1, 4, 9, 0, 1, 4, 9, 0, 1, 4, 9, 0, 1, 4, 9];
    let b      = vec![0, 2, 6, 0, 0, 1, 4, 9, 0, 1, 4, 9, 0, 1, 4, 9];
    mul_array_float(fa.as_mut_slice(), fb.as_slice());
    mul_array(a.as_mut_slice(), b.as_slice());
    println!("{:?} {:?}", a, fa);
}

$ rustc -C opt-level=3 -Z force-overflow-checks=no --emit asm intint.rs
maxim@kudzu:~/depot/voxoz/kernel/tests$ cat intint.s | grep vmul
 vmulsd (%rdi,%rax,8), %xmm0, %xmm0


мы видим что сгенерировалась vmulsp (%rdi,%rax,8), %xmm0, %xmm0
но мы точно знаем, что в этом случае возможно применение инструкции vmulpd (%rdi,%rax,8), %ymm0, %ymm1
Эта инструкция есть точно в AVX, но почему-то Rust ее не генерирует.
Возможно это связано с переполнением, которе мы пытаемся отключить, но это не помогает.
Хочется какой-то референсный код с которым можно сравниваться бенчится.

gist: https://gist.github.com/5HT/dfbde5179fb6112e921fa686a5e459f0

РАССЛЕДОВАНИЕ В КАМЕНТАХ

По пути было перепробовано несколько интринсикс библиотек: x86Intrin (Intel) и llvmint/simdty (LLVM). Раст для векторизации использует встроенную core::intrinsics.
sea

Дефорестизационные Интерпретаторы O2

Тут nponeccop говорит, что наши JIT интерпретаторы говно, вручную мы аллоцируем регистры или через LLVM калейдоскоп, и что надо делать интерпретаторы с реврайт рулами которые делают фьюжин на стадии прекомпиляции. Такие интерпретаторы надо выделить в отдельный класс О2, например, а О класс пускай включает в себя все нормальные интерпретаторы, включая CPS и JIT.

Примеры элиминаторов или правила дефостеризации для стримов и листов:

stream (unstream s) = s
foldr k z (build g) = g k z

where

foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
build g (:) []
stream :: List -> Stream
unstream :: Stream -> List

Приложения в промышленности: векторизация, SIMD конвеерация

__________________
[1]. https://github.com/flypy/flypy/blob/master/docs/source/fusion.rst#id19
[2]. http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.36.5748&rep=rep1&type=pdf
[3]. http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=CF2161C30B69C13CB86B4CAB32E6F607?doi=10.1.1.421.8551&rep=rep1&type=pdf
sea

Eta Lang

Ну что пацаны — я конечно охуел. http://eta-lang.org Поддерживается много пакетов https://github.com/typelead/eta-hackage Отличные примеры, Прекрасный сайт. Проделана титаническая работа. Индусы доказали, что они сыны Будды, Кришны и Шивы, а не шудры. Кстати сделано действительно в Бангалоре! Я вообщем влюбился в этих пацанов: FFI божественный, ну охуенно просто все! Оригинальный GHC, синтаксические расширения, самый совсместимый хаскель из всех возможных. Будущее уже здесь, уверен пойдут форки и на другие платформы (если нужно будет). За джаву видно кто-то очень хорошо заплатил, видна не только командная работа но и комюнити. Кароче заебись я рад, что мир стал чуточку лучше. Этот феномен несомненный позитив в угорюмом энтерпрайз мире. И если существовало бы анти ебаное ИТ, то в него нужно было бы вбросить эту новость.

Жалко что у меня нет столько ресурсов, чтобы ебануть такого уровня движуху :-) Ну там на самом деле все звезды в проекте и длился он давно. Поскольку я такими ресурсами не располагаю — мы играем всегда очень тонко, кода через себя пропустить возможно немного и выбирать надо самое существенное, поэтому моя судьба наверно всегда маргинальная узкоспециализированная ниша. Главное ведь сделать не много, а хорошо!