シンプルなllvm / libjitテストパートII、同じ+ gnu稲妻
この記事は、エラトステインのふるいの例でJust In Timeコンパイルllvmとlibjitのライブラリのパフォーマンスを比較した、
Simple test libjit vs llvmの続きです。
この記事は、まったく同じ問題を解決します-別のJITライブラリーを使用したエラトステネスのふるい-GNU
lightning 。
gnu lightningに関するいくつかの言葉-実際、これはまったくライブラリではなく、実行可能バッファを形成するマクロのセットです。
と同じソリューション
GNUライトニング
001 : #include <stdio.h>
002: #include <lightning.h>
003: #include <math.h>
004: #include <string.h>
005:
006: static jit_insn codeErato[ 1024 ];
007: static jit_insn codemain[ 1024 ];
008:
009: typedef int ( * pifi)( int ); /* Pointer to Int Function of Int */
010: typedef void ( * pvfv)( void ); /* Pointer to void Function of void */
011: char a[ 100000 ];
012:
013: int main ()
014: {
015: pifi erato = (pifi) (jit_set_ip(codeErato).iptr);
016: pvfv func_main;
017: int n, ii;
018: jit_insn * for_cond, * for_end, * end_if, * while_cond, * while_end,
019: * main_for_beg, * main_for_end;
020:
021: jit_prolog( 1 );
022: n = jit_arg_i(); /* n = arg_i */
023:
024: jit_getarg_ui(JIT_V0, n); /* V0 = n */
025: jit_extr_i_f(JIT_FPR0, JIT_V0);
026: jit_prepare( 1 );
027: jit_pusharg_f( JIT_FPR0);
028: jit_finish( sqrtf);
029: jit_retval(JIT_FPR0);
030: jit_roundr_f_i(JIT_V1, JIT_FPR0); /* V1 = q */
031:
032: jit_movi_p(JIT_V2, a); /* V2 = a*/
033: jit_movi_i(JIT_R0, 1 );
034: jit_prepare( 3 );
035: jit_pusharg_i(JIT_V0); /* size_t n */
036: jit_pusharg_i(JIT_R0); /* int c - fillcahr */
037: jit_pusharg_p(JIT_V2); /* array to fill */
038: jit_finish(memset);
039:
040: jit_movi_ui(JIT_R0, 2 ); /* i = 1 (R0)*/
041: for_cond = jit_get_label();
042: for_end = jit_bgtr_ui(jit_forward(), JIT_R0, JIT_V1);
043: jit_ldxr_c(JIT_R2, JIT_V2, JIT_R0);
044: end_if = jit_beqi_ui(jit_forward(), JIT_R2, 0 );
045: jit_mulr_ui(JIT_R1, JIT_R0, JIT_R0); /* j = R1 */
046: while_cond = jit_get_label();
047: while_end = jit_bgtr_ui(jit_forward(), JIT_R1, JIT_V0);
048: jit_stxr_c(JIT_V2, JIT_R1, 0 );
049: jit_addr_ui(JIT_R1, JIT_R1, JIT_R0);
050: jit_jmpi(while_cond);
051: jit_patch(while_end);
052: jit_patch(end_if);
053: jit_addi_ui(JIT_R0, JIT_R0, 1 );
054: jit_jmpi(for_cond);
055: jit_patch(for_end);
056:
057: jit_movr_ui(JIT_RET, JIT_R1);
058: jit_ret();
059: jit_flush_code(codeErato, jit_get_ip().ptr);
060:
061: func_main = (pvfv) (jit_set_ip(codemain).iptr);
062: jit_prolog( 0 );
063: jit_movi_ui(JIT_V0, 1 );
064: main_for_beg = jit_get_label();
065: main_for_end = jit_bgti_ui(jit_forward(), JIT_V0, 100000 );
066: jit_movi_ui(JIT_R0, 50000 );
067: jit_prepare( 1 );
068: jit_pusharg_ui( JIT_R0);
069: jit_finish(erato);
070: jit_addi_ui(JIT_V0,JIT_V0, 1 );
071: jit_jmpi(main_for_beg);
072: jit_patch(main_for_end);
073: jit_ret();
074: jit_flush_code(codemain, jit_get_ip().ptr);
075:
076: puts( "Go" );
077: func_main();
078: return 0 ;
079: }
080:
コンパイルして実行:
$ gcc lightest.c -lm -o lightest
$ for i in `seq 1 10`; do /usr/bin/time -f '%U' ./lightest ; done
32.80
32.59
32.57
32.55
32.53
32.59
32.53
32.69
32.54
32.53
合計平均リードタイム32.59
前の記事で得られた結果と結果を組み合わせます。
Jitライブラリ | 秒単位の実行時間(少ない=良い) |
---|
LLVM | 13.77 |
---|
リブジット | 14.17 |
---|
GNUライトニング | 32.59 |
---|
そして情報だけのために: |
gcc -O0 | 50.09 |
---|
gcc -O1 | 13.79 |
---|
つまり、gnu稲妻の結果、発射速度は、Cプログラムでコンパイルされた最適化の「なし」と「あり」の間です。
gnu lighningはllvmやlibjitよりも
はるかに低いレベルのインターフェースを提供していると言わなければなりません。 プログラマの良心には多くのことが残っています。 例えば、レジスターの割り当て(Lightningはこれを行いません。intには6個、float / doubleには6個のレジスターがあり、必要に応じてスピンします)。 たとえば、最適化。
不快なことに、lightinigの場合は、ブロードキャストする
前に自分でコード用のバッファーを割り当てる必要があることに注意してください。 このバッファの必要なサイズはおおよそしか見積もることができないため、これが問題になる可能性があり、間違えた場合にセグメンテーションフォールトをキャッチするリスクがあります。 さらに、サイト上のドキュメントは不正確です。 たとえば、現在のバージョンのLightningではなくなったjit_allocai()を使用します。
ポジティブから-稲妻のAPIのコマンドシステムはよく考えられているので、冗長性で比較すると、稲妻の解決策はlibjitまたはllvmのほぼ2倍短いことがわかります。 すべての稲妻は単なるマクロのセットであるため、サードパーティのライブラリに依存しないプログラムを取得します。 結果の実行可能ファイルのサイズは非常に小さくなります(これはllvmガーデンの小石であり、ファイルサイズは非常に大きいです)。
道徳。
GNU lightningを使用するのは、結果のプログラムがメモリとディスク容量の点で非常に厳しい条件下で動作する場合のみです。 他のすべての場合-libjitまたはllvmは客観的にはより良く安全です。
All Articles