Uh oh!
There was an error while loading. Please reload this page.
Fixed #1061 failure in snippet unit tests due to the instability of np.sum for array with many small floating point numbers - #1080
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@## main #1080 +/- ##
=======================================
Coverage 96.62% 96.63% =======================================
Files 93 93 Lines 15376 15410 +34 =======================================
+ Hits 14857 14891 +34
Misses 519 519 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…ond attempt with disabled jit
seanlaw
left a comment
There was a problem hiding this comment.
@NimaSarajpoor Should the unit tests be failing?
| # This test raises an error if arithmetic operation in ... | ||
| # ... `gpu_stump._compute_and_update_PI_kernel` does not | ||
| # generates the same result if values of variable for mean and std |
For the last two commits, I expected all tests to pass.. My expectation was wrong as I had tested it locally in a different environment. I was able to re-produce the error raised by macOS latest, python 3.9 We are facing the same issue, i.e. the loss of precision in |
I don't understand. How is At the end of the day, what matters is that the answers are the same and not that the performant results are of ultra-high precision |
A SIMPLE EXAMPLE TO BETTER UNDERSTAND THE PROBLEM A REAL EXAMPLE # inputseed=1615np.random.seed(seed)
T=np.random.uniform(-1000.0, 1000.0, 64)
m=10s=3k=3mpdist_T_subseq_isconstant=functools.partial(
naive.isconstant_func_stddev_threshold, quantile_threshold=0.05
)
# other params with defaultpercentage=1.0mpdist_percentage=0.05mpdist_k=NoneI would like to check the 2D array And I want to answer those questions for three cases and, for a different environment: Observation: In Codeimportfunctoolsimportmathimportnaiveimportnumbaimportnumpyasnpfromstumpy.snippetsimport_get_all_profilesdefprint_info(D, m, k, sum_func):
Q=np.full(D.shape[-1], np.inf, dtype=np.float64)
indices=np.arange(D.shape[0], dtype=np.int64) *mforiinrange(k):
min_DQ=np.minimum(D, Q)
sum_min_DQ=sum_func(min_DQ, axis=1)
profile_areas=sum_min_DQidx=np.argmin(profile_areas) Q[:] =np.minimum(D[idx], Q)
snippet_index=indices[idx]
# check min_DQ in latest iterationa=min_DQ[1] # corresponds to snippet index 10b=min_DQ[3] # corresponds to snippet index 30print('Do a and b have the same elements? ', np.all(np.sort(a) ==np.sort(b)))
print('With math.fsum: SUM(a)==SUM(b)? ', math.fsum(a) ==math.fsum(b))
print('With np.sum: SUM(a)==SUM(b)? ', np.sum(a) ==np.sum(b))
returndefcheck_snippets_rare_case():
seed=1615np.random.seed(seed)
T=np.random.uniform(-1000.0, 1000.0, 64)
m=10s=3k=3mpdist_T_subseq_isconstant=functools.partial(
naive.isconstant_func_stddev_threshold, quantile_threshold=0.05
)
percentage=1.0mpdist_percentage=0.05mpdist_k=None# case: naiveprint("="*50)
print("naive")
D=naive.get_all_mpdist_profiles(
T,
m,
percentage,
s,
mpdist_percentage,
mpdist_k,
mpdist_T_subseq_isconstant=mpdist_T_subseq_isconstant,
)
print_info(D, m, k, sum_func=np.sum)
# case: performantprint("="*50)
print("performant")
D=_get_all_profiles(
T,
m,
percentage,
s,
mpdist_percentage,
mpdist_k,
mpdist_T_subseq_isconstant=mpdist_T_subseq_isconstant,
)
print_info(D, m, k, sum_func=np.sum)
# case: performant with disabled JIT print("="*50)
print("performant with disabled JIT")
numba.config.DISABLE_JIT=TrueD=_get_all_profiles(
T,
m,
percentage,
s,
mpdist_percentage,
mpdist_k,
mpdist_T_subseq_isconstant=mpdist_T_subseq_isconstant,
)
print_info(D, m, k, sum_func=np.sum)
returnif__name__=="__main__":
check_snippets_rare_case() |
@NimaSarajpoor Maybe this is a stupid question/comment but I noticed that you generate the distance profiles using Output: Based on this, I am inclined to believe that as long as we can make Let me know what you think. |
NimaSarajpoor
commented
Apr 10, 2025
You are correct. This should resolve the MAIN root cause. One approach is to break down the snippet function and creates a callee that accepts "D" as input (as a side note: this logic can also mean a user can provide their own D to compute snippet??). Then, we can compute D in both naive and performant, and if the values are all close , then we pass only one of them to the callees in both naive and performant versions. What do you suggest? |
I think that the correct thing to do is to understand why the |
NimaSarajpoor
commented
Apr 19, 2025
Let IIUC the goal is to understand the main cause of having different values in (1) First, disable JIT and see if the values are matching. If not, we can try to resolve it. Please let me know if I misunderstood your point. |
I think you've captured it though I wouldn't focus on the changing the performant/NJIT version. If you recall, when we use to compare our performant My suspicion is that the difference between Does that make sense? |
NimaSarajpoor
commented
Apr 21, 2025
YES!!
Right. Let me dig into both and report back. |
NimaSarajpoor
commented
Aug 12, 2025
I checked
I changed the naive version and used the The tests were still failing. So, I switched my attention to those full distance matrices. I extracted all those full distance matrices that were computed in the process in both naive- and the performant- versions. I compared them against each other using As the next step, I think I need to compare the elements of those matrices closely and see if it can help with narrowing down the issue. |
seanlaw
commented
Aug 12, 2025
Sounds good! It's great to see your comments again 👍 |
seanlaw
commented
Jan 10, 2026
I came across this wonderful blog post that describes different ways to sum a list of numbers and I wonder if one of the exact methods might be useful. It looks like |
See issue #1061