francof2a / fxpmath

A python library for fractional fixed-point (base 2) arithmetic and binary manipulation with Numpy compatibility.
MIT License
183 stars 21 forks source link

Slow conversion speed #46

Closed AjinkyaBankar closed 3 years ago

AjinkyaBankar commented 3 years ago

I am using the fxpmath package. I need to convert DNN parameters into the fixed-point format and use individual parameters' binary representation manipulations later. In the end, convert the manipulated binary back to fixed-point format. This procedure consumes a significant time overhead if the DNN size is large. In comparison, a similar process for single-precision floating-point numbers is speedy. Is there any way to speed up?

francof2a commented 3 years ago

A creation of a Fxp object has several stages like: input type identification, best size estimation (if some of the sizing params are missing), overflow/underflow detection, and finally the conversion to fixed-point (integer).

When an array is passed as input value to convert, best size estimation and overflow/underflow detection should check all values, and it is time consuming when the array is huge!

could you tell me about the size of that array and how are you passing it to the Fxp object?

AjinkyaBankar commented 3 years ago

Thanks for your response. My array has approximately 8M parameters. I need to iterate through each of the parameters for the steps mentioned in my earlier post. Therefore, I pass each parameter separately. Please let me know if you need more details.

francof2a commented 3 years ago

You're welcome!

You can convert the full array of weights into a Fxp. It would be faster that convert one by one but the size is going to be the same for all weights, is it a problem for your solution? Another way if create a Fxp with a particular size and reuse it to change its value (in a for loop, for example).

A fixed size conversion into a Fxp object is faster than a previous undefined size, so, if you can define at least one of the size params (n_word, n_frac or n_int) at instantiation, it should improve conversion time.

I performed next example in my PC (doing %timeit):

import numpy as np
from fxpmath import Fxp

x = np.random.normal(0., 1., size=(1000000,))  # an 1M random array

x_fxp = Fxp(x)    
# 58.5 s ± 259 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

x_fxp = Fxp(x, signed=True, n_word=32)
# 59.4 s ± 338 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

x_fxp = Fxp(x, signed=True, n_frac=30)
# 608 ms ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

x_fxp = Fxp(x, signed=True, n_word=32, n_frac=30)
# 592 ms ± 2.61 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

You can also use a already defined Fxp as template for next Fxp creations.

Feel free to copy part of your code if you need a better feedback.

AjinkyaBankar commented 3 years ago

Thank you for your detailed response. My Fxp size is the same for all the parameters, so as you said, it would be faster to convert the entire array into Fxp once. I will contact you if required.

francof2a commented 3 years ago

Great! Remember that indexing is supported by Fxp just like a numpy array. An indexed element is returned as a Fxp, so you can apply same methods to each element. For example:

x_fxp[0]
# fxp-s32/30(0.4204888893291354)

x_fxp[0].bin()
# '00011010111010010100101000111011'

x_fxp[0].get_val()
# 0.4204888893291354

If you consider the issue is solved after testing, please tell me or close the issue. Thanks again for the feedback of this library!

AjinkyaBankar commented 3 years ago

I need to use .bin() method followed by bit-wise manipulations, then convert the manipulated bit string to Fxp, and at last use the .get_val() method. And they still consume a significant time.

francof2a commented 3 years ago

Consider to operate using Fxp directly for bit-wise manipulations instead of using a array of strings returned by .bin() method.

Fxp supports all python's bitwise operators.

AjinkyaBankar commented 3 years ago

That's wonderful! It worked for me. Thanks for your suggestion.

francof2a commented 3 years ago

Great! I consider the issue solved. Thanks for the feedback!