N-Prolog 컴파일러 최적화

소개



N-Prolog에는 컴파일러도 장착되어 있습니다. 당초 최적화를 실시하지 않았기 때문에 인터프리터에 비해 40% 정도의 개선밖에 볼 수 없었습니다. 일정한 결정성과 말미 재귀의 술어에 대해 최적화를 했습니다.



아래는 Queens 문제 코드의 일부입니다. 여왕이 운반 근육에 있는지 여부? 를 판정하는 것입니다. 이것은 최적화가 가능합니다.

nodiag([], _, _).
nodiag([N|L], B, D) :-
    D =\= N - B,
    D =\= B - N,
    D1 is D + 1,
    nodiag(L, B, D1).



생성할 C 코드


int b_nodiag(int arglist, int rest);
int b_nodiag(int arglist, int rest){
int n,head,varD1,varN,varL,varB,varD,var2,var1;
n = Jlength(arglist);
if(n == 3){
loop:
Jinc_proof();
var2 = Jmakevariant();
var1 = Jmakevariant();
head = Jwcons(NIL,Jwcons(var2,Jwcons(var1,NIL)));
if(Jcar(arglist) == NIL && 1) return(Junify(arglist,head));
varN = Jcar(Jcar(arglist));
varL = Jcdr(Jcar(arglist));
varB = Jcar(Jcdr(arglist));
varD = Jcar(Jcdr(Jcdr(arglist)));
{if(!Jnot_numeqp(Jderef(varD),Jminus(Jderef(varN),Jderef(varB)))) return(NO);
if(!Jnot_numeqp(Jderef(varD),Jminus(Jderef(varB),Jderef(varN)))) return(NO);
varD1 = Jplus(Jderef(varD),Jmakeint(1));
arglist = Jwcons(varL,Jwcons(varB,Jwcons(varD1,NIL)));
goto loop;
}}return(NO);
}


벤치마크



세계 최고속급 SWI-Prolog와 비교했습니다. 9queens를 표시해 16회 연속해서 실행하는 것입니다.





22% 정도 늦어지고 있습니다. 그러나, 역사가 있는 swi에 비해 뭐 그렇게 나쁘지 않은 속도를 내고 있습니다.

또한



한층 더 최적화 가능한 코드의 수비 범위를 넓혀 갈 예정으로 하고 있습니다.

컴파일러에 대한 자체 확장 술어



n_clause_with_arity/3 제1항에 술어명, 제2항에 항수를 주고, 그 요건을 만족하는 모든 절, 술어를 제3항에 unify한다.

n_variable_convert/2 제1항에 주어진 절에 포함되는 변수를 var*형식하여 리스트로서 제2항에 unify한다.
n_atom_convert/2 제1항에 주어진 아톰을 C언어의 함수명으로서 사용할 수 있도록 변환한다.
지금 : 을 _로 변경하고 있습니다.
n_filename/2 제1항에서 주어진 파일명으로부터 식별자를 제거한 아톰을 제2항에 unify한다.
n_arity_count/1 제1항에서 주어진 아톰을 술어명으로 하는 모든 절, 술어의 항수를 리스트로 하여 제2항에 unify한다.
n_reconsult_predicate_list/1 reconsult/1에서 읽는 파일의 모든 술어, 절의 술어명과 항수를 P/A의 형식으로 한 리스트로 하여 제1항에 unify한다.

n_reconsult_predicate/1 reconsult/1에서 읽은 파일의 모든 술어 이름을 제1항에
unify한다. 뒤로 트럭한다.
n_defined_predicate/1절의 정의를 술어라면 yes, 그렇지 않으면 no
n_compiler_variable/1 컴파일러에서 사용하는 형식의 변수라면 yes 그렇지 않으면 no (예 varX)
n_generate_variable/2 제1항의 절에 포함되는 변수를 varX와 같은 형식으로 리스트로서 제2항에 unify한다.
n_generate_all_variable/1 제1항에서 주어진 아톰을 술어명으로 하는 모든 술어, 절에서 사용되고 있는 변수를 var*의 형식으로 리스트로서 제2항에 unify한다.
n_compiler_anoymous/1 제1항이 var_와 같이 컴파일러 내부 형식의 익명 변수인 경우에 yes 그렇지 않으면 no
n_compiler_variable/1 제1항이 varX와 같이 컴파일러 내부 형식의 변수인 경우에는 yes 그렇지 않으면 no
n_argument_list/2 첫 번째 인수의 술어의 항 부분을 목록으로 변환하여 두 번째 인수로 unify합니다.
n_decompose/3 제1 인수를 그것이 어쨌든, car와 cdr로 분해해, 제2, 제3 인수에 unify한다.
n_property/2 첫 번째 인수에 따라 두 번째 인수에 다음 원자를 unify합니다.
내장 술어 = builtin, 사용자 술어 = predicate, 함수 = function, operation = operation, 컴파일된 술어 = compiled

n_findatom 제 1 인수의 아톰으로 제 2 인수의 속성을 가지는 것의 실 주소를 제 3 인수에 unify 한다.
속성은 아래와 같다.
내장 술어 = builtin, 사용자 술어 = predicate, 함수 = function, operation = operation, 컴파일된 술어 = compiled

좋은 웹페이지 즐겨찾기