Modify

Ticket #9233 (closed Bugs: wontfix)

Opened 3 years ago

Last modified 13 months ago

Suboptimal shift by multiples of 8 bits

Reported by: psiha Owned by: johnmaddock
Milestone: To Be Determined Component: multiprecision
Version: Boost 1.54.0 Severity: Optimization
Keywords: Cc:

Description

It seems to me that the operation from the subject is needlessly fat, as if it is using a generic implementation for a generic/'random' number of bits...

Attachments

Change History

comment:1 Changed 3 years ago by johnmaddock

  • Status changed from new to closed
  • Resolution set to wontfix

I don't believe there's any way to improve this - shifts by whole numbers of "limbs" are optimized, but individual bytes are not in a suitable order for a std::memmove for example.

comment:2 Changed 13 months ago by psiha

Maybe you could add/separate specialized functions for shifting: for whole limbs, for whole bytes and 'generic'. Then the shift operator can be implemented as if ( bits % limb_bits == 0 ) shift_limbs(); elseif ( bits % 8 == 0 ) shift_bytes(); else { generic() }; and rely on IPO to directly select the optimal implementation when bits is a compile time constant...

ps. why are limbs on win64 32bit integers (as opposed to 64 bit ones)?

Last edited 13 months ago by psiha (previous) (diff)

comment:3 follow-up: ↓ 4 Changed 13 months ago by johnmaddock

Fixed in  https://github.com/boostorg/multiprecision/commit/cb1a41835f4566987b96c7a7034088e22d83f77b

It turns out that memmove is (very slightly) faster than moving whole limbs so that's the preferred method when available.

Limbs are half the size of the largest available integers - so 32-bit for msvc as there's no 128-bit integer support (unlike mingw for example).

comment:4 in reply to: ↑ 3 Changed 13 months ago by psiha

Replying to johnmaddock:

Fixed in  https://github.com/boostorg/multiprecision/commit/cb1a41835f4566987b96c7a7034088e22d83f77b

Thanks John :) I no longer use/need this functionality so I didn't test but from a cursory skim it looks good...except that maybe the (little) endian checks are not really necessary: if you make them in only one place - where you decide on the underlying/raw/limb layout - if you order the limbs in 'machine endianess' (I'm guessing) the rest of the code can be endianness agnostic (and more readily assume correct byte ordering/use memcpy/move/set more easily)...

It turns out that memmove is (very slightly) faster than moving whole limbs so that's the preferred method when available.

It's also smaller (one call instead of a loop for every instantiation;)

Limbs are half the size of the largest available integers - so 32-bit for msvc as there's no 128-bit integer support (unlike mingw for example).

Thanks for the explanation ;)

comment:5 Changed 13 months ago by anonymous

if you order the limbs in 'machine endianess' (I'm guessing) the rest of the code can be endianness agnostic (and more readily assume correct byte ordering/use memcpy/move/set more easily)

No I'd have to rewrite everything - multiplication, addition, subtraction, the works. Two versions for each, one little endian, one big. And I'd have no means of testing the big endian code either...

Not going to happen, sorry!

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.