From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr 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 A1651BC37 for ; Wed, 28 Oct 2009 18:10:04 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AoMCAAMY6ErUGyoGkWdsb2JhbACbPgEBAQEJCwoHEwO+bYQ/BIFh X-IronPort-AV: E=Sophos;i="4.44,641,1249250400"; d="scan'208";a="49413183" Received: from smtp6-g21.free.fr ([212.27.42.6]) by mail4-smtp-sop.national.inria.fr with ESMTP; 28 Oct 2009 18:09:22 +0100 Received: from smtp6-g21.free.fr (localhost [127.0.0.1]) by smtp6-g21.free.fr (Postfix) with ESMTP id 72313E08212; Wed, 28 Oct 2009 18:09:16 +0100 (CET) Received: from [192.168.1.3] (che78-2-82-237-71-191.fbx.proxad.net [82.237.71.191]) by smtp6-g21.free.fr (Postfix) with ESMTP id 2ECB4E08223; Wed, 28 Oct 2009 18:09:13 +0100 (CET) Message-ID: <4AE87AB9.5020607@inria.fr> Date: Wed, 28 Oct 2009 18:09:13 +0100 From: Xavier Leroy User-Agent: Thunderbird 2.0.0.4 (X11/20070620) MIME-Version: 1.0 To: Goswin von Brederlow Cc: caml-list@inria.fr Subject: Re: [Caml-list] How to read different ints from a Bigarray? References: <87eiond3of.fsf@frosties.localdomain> In-Reply-To: <87eiond3of.fsf@frosties.localdomain> X-Enigmail-Version: 0.95.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Spam: no; 0.00; bigarray:01 buffer:01 elt:01 bigarray:01 buf:01 buf:01 elt:01 ocaml's:01 typechecker:01 ocaml:01 ocaml:01 endian:01 overkill:01 byte:01 bigarrays:01 Goswin von Brederlow wrote: > I'm working on binding s for linux libaio library (asynchron IO) with > a sharp eye on efficiency. That means no copying must be done on the > data, which in turn means I can not use string as buffer type. > > The best type for this seems to be a (int, int8_unsigned_elt, > c_layout) Bigarray.Array1.t. So far so good. That's a reasonable choice. > Now I define helper functions: > > let get_uint8 buf off = buf.{off} > let set_uint8 buf off x = buf.{off} <- x > > But I want more: > > get/set_int8 - do I use Obj.magic to "convert" to int8_signed_elt? Not at all. If you ask OCaml's typechecker to infer the type of get_uint8, you'll see that it returns a plain OCaml "int" (in the 0...255 range). Likewise, the "x" parameter to "set_uint8" has type "int" (of which only the 8 low bits are used). Repeat after me: "Obj.magic is not part of the OCaml language". > And endian correcting access for larger ints: > > get/set_big_uint16 > get/set_big_int16 > get/set_little_uint16 > get/set_little_int16 > get/set_big_uint24 > ... > get/set_little_int56 > get/set_big_int64 > get/set_little_int64 The "56" functions look like a bit of overkill to me :-) > What is the best way there? For uintXX I can get_uint8 each byte and > shift and add them together. But that feels inefficient as each access > will range check Not necessarily. OCaml 3.11 introduced unchecked accesses to bigarrays, so you can range-check yourself once, then perform unchecked accesses. Use with caution... > and the shifting generates a lot of code while cpus > can usualy endian correct an int more elegantly. > > Is it worth the overhead of calling a C function to write optimized > stubs for this? The only way to know is to benchmark both approaches :-( My guess is that for 16-bit accesses, you're better off with a pure Caml solution, but for 64-bit accesses, a C function could be faster. - Xavier Leroy