-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make @big_str
allocate at runtime by default
#41792
Comments
Since Julia's numbers are considered immutable the current behavior is already "safe". Mucking around with internals can almost always turn something safe into unsafe. So using this specific example doesn't look super compelling to me. |
It's very common to use mutating operations on I've never read anywhere that |
The world that the Julia documentation presents is that of immutable big numbers so the manual will not mention anything that has to do with their mutability since that is outside the "world". It is on the people using the internals to make sure that this is done safely, for example using Why should everyone get worse performance in the common use case instead of the people doing the mutation just swapping over to the correct thing to use? |
Personally, I would be happy with a warning in the docstring of the
That seems to refer to the regex macro (and don't think it's common to mutate those), it's not mentioned near the I think a mention of this in the docstring of (As for performance, I would guess most users concerned with the performance of |
The problem with adding "a warning in the docstring of the |
I understand your argument, and it's compelling. It just seems like having 'semantically immutable' numbers that are mutable under the hood, and then 'semi-exposing' it through this macro (and obliquely documenting it in the macro chapter) is unfortunate. Is this optimization used by the |
I think we should change this because users who aren't mutating big nums won't see a major performance impact, since every operation they do will construct a new BigNum anyway. |
To me it's already inconsistent. If
so changing this really shouldn't have an impact on naive uses of |
|
@vtjnash, do we have any examples where making a copy would be a noticable slowdown? If not, I don't see a good reason to not do this. Sure, it only helps people that access internals, but those internals are necessary foror writing high performance code |
Out of curiosity, is this documented anywhere? I know that the iteration interface, abstract array interface, and several others are documented in the section on interfaces but I haven't encountered any documentation on what it means to be a |
Agree with @KristofferC and @vtjnash here: the problem in this example is mutating a semantically number, not that |
I would add that this might seem like a harmless safety precaution, but let's say people start relying on this and later we improve compiler support for BigInts so that the compiler is able to recognize that a BigInt value doesn't escape and can be modified? That is much harder to do if people have started to rely on the ability to mutate BigInts. If they're genuinely immutable, it's much easier to optimize them. Consider this code: function f(n::Integer)
s = n
while n > 0
n ÷= 2
s += n
end
return s
end If we can count on function f(n::Integer)
s = copy(n)
n = copy(n)
while n > 0
div!(n, 2)
add!(s, n)
end
return s
end However, if we have to worry about someone mutating |
Wouldn't the proposed change here be strictly better if we ever wanted to do some escape analysis though? Right now the allocation is hidden somewhere in macro expansion, so it can't really ever be elided. If it happened at runtime, the compiler would theoretically at least have a lot more leeway. Since Has there been previous discussion about just embracing the mutability of |
#29168 (comment) is one comment about it. |
But this is difficult to understand for those who use the mutating interface, because documenting it is discouraged, and there's a bit of a mental leap required to realize it. |
I don't mean to take over this discussion about I see the argument for having Maybe I'm missing something here though and having a Regarding the transform mentioned by @StefanKarpinski: The reason this can't be done today by a library author right now is because I've thought about using |
FWIW, there was a PR trying to make |
From Slack, here is a MWE of a recent problem caused by this issue: function foo(prec)
setprecision(BigFloat, prec)
return big"0.23"
end
foo(50) === foo(100) # return true, unexpectedly The issue here is that |
I'd say the While the Julia standard library pretends that all
|
This seems to be a performance footgun, for something that is defined as being non-mutated in Base. |
But to work efficiently with |
We fairly often see newcomers to Julia post something like this:
Where the response is
And so people get the impression that
big"X"
simply creates aBigInt
from X. But it doesn't, not really. Instead, the value is created as a constant at compile-time. This is correct behaviour, as documented in the manual section on string literals, but it can lead to nasty bugs:Spot the problem?
Again, this is not a bug, it's correct behaviour, but it would be nicer if the default behaviour was safe (new allocation with the macro) and the opt-in behaviour was fast (re-use same object), instead of the other way around. I realize this cannot be solved in general for
@X_str
, but perhaps just for@big_str
?For what it's worth,
BioSequences
uses a flag on its@dna_str
macro which controls "dynamic" vs "static" allocation for DNA strings.The text was updated successfully, but these errors were encountered: