From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id 1D1EBBC37 for ; Fri, 15 Jan 2010 18:43:18 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AqQCAC44UEtKfVwaimdsb2JhbACPeIFxghmHQT8BAQEKCQwHEQWwAIEyhTaGYwECAwWELASKfA X-IronPort-AV: E=Sophos;i="4.49,282,1262559600"; d="scan'208";a="54103196" Received: from qw-out-2122.google.com ([74.125.92.26]) by mail4-smtp-sop.national.inria.fr with ESMTP; 15 Jan 2010 18:43:17 +0100 Received: by qw-out-2122.google.com with SMTP id 8so237218qwh.15 for ; Fri, 15 Jan 2010 09:43:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:reply-to:date:message-id :subject:from:to:content-type; bh=OHuq3lKKTGeW1nNaLL+WknFcS4vBL4z+IRdXBknI4us=; b=Xj2fQsYr5n2Dw12gjyPhWjD9UDdab/p3iOEAujlp/Hoa1v9rzictznBHpQYs0yP/0O pB+2fxroXz0hN/QGvmqMPTJS74NUCyyPg5OyK28/W/cVUCD2b5uBLP3yHZ7FE312kpQ8 UWIOcK+qu+s2xO3F6Z91eShzTZexMDSM0dkWo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:reply-to:date:message-id:subject:from:to:content-type; b=O+721RKp3OaHY8m6KMje/VZHIYu+eP6m6XsdeoAiwW6pDX14klsBeOPey+e5Sbw1xw Hf47xpSX58YYIm/LaBYGv6uDDsK4dYJg9dWiZEyBUPH0tBtpc5qThnRpexJLDP75SCq6 3Mez7PjVr5bEJUgK2FLpTWidhgt8Ht+r+5sK0= MIME-Version: 1.0 Received: by 10.103.84.27 with SMTP id m27mr1263780mul.19.1263577395748; Fri, 15 Jan 2010 09:43:15 -0800 (PST) Reply-To: odalric.maillard@inria.fr Date: Fri, 15 Jan 2010 18:43:15 +0100 Message-ID: <406c33611001150943o2aeb2429qefa22f1102699730@mail.gmail.com> Subject: OCaml, C, Garbage Collector etc From: Odalric-Ambrym Maillard To: caml-list@yquem.inria.fr Content-Type: multipart/alternative; boundary=0016e65aee2ad1e1eb047d378921 X-Spam: no; 0.00; ocaml:01 ocaml:01 le-gall:01 val:01 val:01 alloc:01 wosize:01 printf:01 camlparam:01 camlreturn:01 camlparam:01 camlreturn:01 malloc:01 sizeof:01 malloc:01 --0016e65aee2ad1e1eb047d378921 Content-Type: text/plain; charset=ISO-8859-1 Hello, I am currently writin an algorithm in OCaml. Since its a learning algorithm, I would like to uses some existing code, which is mainly in C. For the program to be usable by others, I write the main structure in C and make call to some functions in Ocaml when needed. Well, I thought I had understood how this works. but obviously, there is omething wrong, for the program crashes, and it seems, according to my tests and sylvain le-gall, that it is due to problem concerning the garbage collector. All I need is this: - say I have an OCaml function psi : int -> float array -> float. - say have a C matrix of data: double ** x_data, and a vector double * y_data. Then, I just need to create, in C a matrix, double ** psi_mat, with values psi m x_i at position m,i, where w_i is the ith row of x_data. One way to do that (not the most efficient) is to create the function psi_c corresponding to the OCaml psi function, and then use it in the code. For instance, let consider this code: -------------------------------------------------------------------- double psi_c(int m, int dim_x,double * x){ int d; CAMLlocal2(val_M,val_x); val_m = Val_int(m); val_x = caml_alloc(dim_x * Double_wosize, Double_array_tag); for(d=0;dHello,

I am currently writin an algorithm in OCaml. Since its a = learning algorithm, I would like to uses some existing code, which is mainl= y in C.
For the program to be usable by others, I write the main structu= re in C and make call to some functions in Ocaml when needed.

Well, I thought I had understood how this works. but obviously, there i= s omething wrong, for the program crashes, and it seems, according to my te= sts and sylvain le-gall, that it is due to problem concerning the garbage c= ollector.

All I need is this:
- say I have an OCaml=A0 function psi : int ->= ; float array -> float.
- say=A0 have a C matrix of data:=A0 double *= * x_data, and a vector double * y_data.

Then, I just need to create,= in C a matrix, double ** psi_mat, with values psi m x_i at position m,i, w= here w_i is the ith row of x_data.
One way to do that (not the most efficient) is to create the function psi_c= corresponding to the OCaml psi function, and then use it in the code.
<= br>For instance, let consider this code:
--------------------------------------------------------------------
double psi_c(int m, int dim_x,double * x){
= =A0 int d;

=A0 CAMLlocal2(val_M,val_x);
=A0 val_m =3D Val_int(m);=
=A0 val_x =3D caml_alloc(dim_x * Double_wosize, Double_array_tag);
=A0 for(d=3D0;d<dim_x;d++){
=A0=A0=A0 printf("Stored %f",x[= d]);
=A0=A0=A0 Store_double_field(val_x, d,x[d]);
=A0 }

=A0 re= turn(Double_val(caml_callback2( *closure_psi, val_m, val_x)));=A0
=A0 }=
--------------------------------------------------------------------
whe= re of course, the following variable is declared globally:

static va= lue * closure_psi =3D NULL;

and=A0 somewhere in the main we have:
=A0if (closure_psi =3D=3D NULL) {
=A0=A0=A0 closure_psi =3D (value*)= caml_named_value("psi_Ocaml");
=A0 }


Well, this co= de does not work, meaning that a call to this function may generate either = segmentation fault, or infinite loop, or just the correct expected result. = This impredictible behaviour seems to come from the Garbage collector that = moves blocks it should not move here...

But generally, you can handle this when you write a function C from OCa= ml, since you have a function of the form:

value my_function(value x= ){
CAMLparam1(x)
...
CAMLreturn(...)
}
thus CAMLparam and CA= MLreturn seem to do the job.

But how to do that when you are on the other side ??

I really do= not understand hoxw to do that. I suspect moreover that there is something= specific to be done due to the fact I use double values, which are handled= in a specific way by OCaml (so may be the same code would work with int va= lues (or not ??) ? anyway I need double).




Eventually, what I would prefer is to do only one allocatio= n of the ith row x_i to call the corresponding OCaml, like the following co= de (which works when executed !?!) :


---------------------------= ---------------------------------------------------------------------
void make_psi_matrix(int Mnumber_of_compressed_features,
=A0=A0=A0 =A0= =A0=A0 =A0=A0=A0=A0 int Knumber_of_training_data,
=A0=A0=A0 =A0=A0=A0 = =A0=A0=A0=A0 int Dspace_dimension,
=A0=A0=A0 =A0=A0=A0 =A0=A0=A0=A0 dou= ble **x_train,
=A0=A0=A0 =A0=A0=A0 =A0=A0=A0=A0 double ***psi_matrix) {=

=A0 double * xk;
=A0 double ** psi_matrixm;
=A0 int m,d,k;
=A0
=A0=A0=A0 xk =3D malloc (Dspace_dimension * sizeof (double));
= =A0 *psi_matrix =3D malloc (Mnumber_of_compressed_features * sizeof (double= *));
=A0 for(m=3D0,psi_matrixm =3D *psi_matrix;
=A0=A0=A0=A0=A0 m<Mnumber_of_compressed_features;
=A0=A0=A0=A0=A0 m+= +,psi_matrixm++) {
=A0=A0=A0 *psi_matrixm =3D malloc=A0 (Knumber_of_trai= ning_data * sizeof (double));
=A0 }

=A0 CAMLlocal2(val_x,val_M); = =A0=A0=A0
=A0 val_x =3D caml_alloc(Dspace_dimension * Double_wosize, Do= uble_array_tag);
=A0 for(k=3D0;k<Knumber_of_training_data;k++){
=A0=A0=A0 xk =3D x_tra= in[k];
=A0=A0=A0 //printf("k :%d/%d\n",k,Knumber_of_training_d= ata);=A0
=A0=A0=A0 for(d=3D0;d<Dspace_dimension;d++){
=A0=A0=A0= =A0=A0 //printf("Store %f at position %d,%d...",xk[d],k,d);
=A0=A0=A0=A0=A0 Store_double_field(val_x, d, xk[d]);
=A0=A0=A0=A0=A0 // = printf("...ok\n");
=A0=A0=A0 }=A0=A0=A0=A0=A0

=A0=A0= =A0 for(m=3D0;m<Mnumber_of_compressed_features;m++){
=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0 val_M =3D Val_int(m);
=A0=A0=A0=A0=A0 ((*psi_matrix)= [m])[k] =3D Double_val(caml_callback2( *closure_psi, val_M, val_x));
=A0=A0=A0=A0=A0
=A0=A0=A0 }
=A0=A0=A0 }
=A0

}


---------------------------------------------------------------------------= ---------------------
What is very suprisin is that its brother that out= puts a vector y_predict of prediciton does not work at all (though the code= =A0 is very similar for the Ocaml call).
Thus we have the same problem again : how to handle=A0 this more complicate= d case ? Suppose I can use CAMLparam in the following code : How can I real= luy use it ?? I really do not know because of the loops.

---------------------------------------------------------------------------= ---------------------
void predict(double * beta,
=A0=A0=A0 =A0=A0= =A0=A0 int Mnumber_of_compressed_features,
=A0=A0=A0 =A0=A0=A0=A0 int Ds= pace_dimension,
=A0=A0=A0 =A0=A0=A0=A0 int Knumber_of_data,
=A0=A0=A0 =A0=A0=A0=A0 double **x_data,
=A0=A0=A0 =A0=A0=A0=A0 double **= y_predict) {


=A0 int d,m,k;
=A0 double s,aux_val;
=A0 do= uble *xk;

=A0 xk =3D malloc (Dspace_dimension * sizeof (double));=A0 *y_predict =3D malloc (Knumber_of_data * sizeof (double));
=A0 CAMLlocal2(val_x,val_M); =A0=A0=A0
=A0 val_x =3D caml_alloc(Dspace_= dimension * Double_wosize, Double_array_tag);
=A0 for(k=3D0;k<Knumber= _of_data;k++){
=A0=A0=A0 xk =3D x_data[k];
=A0=A0=A0 for(d=3D0;d<D= space_dimension;d++){
=A0=A0=A0=A0=A0 Store_double_field(val_x, d, xk[d]= );
=A0=A0=A0 }=A0=A0=A0=A0=A0
=A0=A0=A0 s =3D 0;
=A0=A0=A0 for(m=3D0;m&= lt;Mnumber_of_compressed_features;m++){=A0=A0=A0=A0=A0
=A0=A0=A0=A0=A0 = val_M =3D Val_int(m);
=A0=A0=A0=A0=A0 s =3D s + beta[m]*Double_val(caml_= callback2( *closure_psi, val_M, val_x));=A0=A0=A0=A0=A0
=A0=A0=A0 }
= =A0=A0=A0 (*y_predict)[k] =3D s;
=A0 }
}
=A0
---------------------------------------------------------------------------= ---------------------


So, does anybody has a solution, idea, or = even a good example (using vectors or matrix of double, I insist) that coul= d help ?

Have=A0 a good day,
Odalric-Ambrym

--0016e65aee2ad1e1eb047d378921--