-
Notifications
You must be signed in to change notification settings - Fork 119
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
Another problem with datahandle #2458
Comments
The problem (no solution yet) turns out to be explicitly handling a pointer (call it POINTER c} in a VERBATIM block via
I.e. a typical legacy block to determine if the pointer is valid.
When that is evaluated and _p_c points to a voltage, then the error is
A more or less minimal example of this is
and
execute with
If c is set to point to
If c is never set from python, then one does get the output
A user written pointer test is still useful, since
gives a segfault if the pointer is not set. |
While reading the generated code I spot he following:
This looks surprising, because My first guess is that this is a code generation bug and it should have generated:
Further down there's code that suggests that we're using the SoA containers for mechanisms, i.e. I would guess that we'd just have a column with
I've locally edited the file
it didn't create a warning and didn't crash either. @nrnhines do you think my guesses are reasonable? If yes, I'll try to find out how to fix the code generation. |
I think you're correct about the semantics of #define on_init *_ppvar[2]._pval
#define _p_on_init _ppvar[2]._pval where they're literally the same except one is dereferenced. I don't know why you'd ever have a In my code when I ran into this the other day, I simply changed my (I'd argue for getting rid of the |
There's a subtlety here. The first is that nrn/src/neuron/container/data_handle.hpp Lines 60 to 61 in 21f1654
and the other isn't: nrn/src/neuron/container/generic_data_handle.hpp Lines 36 to 38 in 21f1654
This is what I mean when I say that
You can peak inside and see the
Yes, that's a pointer to a Edit: The above is only true if |
Yes. But I think the SoA implementation of POINTER (like the previous implementations from inception of the POINTER keyword onward) isn't providing permutation invariance, reallocation invariance, and invalidation error messaging (except for itself! Not what it is pointing at.) that we now expect from data handles (at least for data handles to RANGE variables). Sounds like what is wanted is "POINTER is a data handle to a data handle".
more or less was orginially designed to point to a range variable. In this case the user restricts them to point to a voltage at another location. Though it has an obvious use also for HOC scalar, or ultimately, any double, e.g. A Vector element. Sadly, in VERBATIM blocks, POINTER was at hand to serve for pointer to Vector or Random123, or, indeed, any HOC Object* Going back to "POINTER is a data handle to a data handle". That is in tension with the desire for optimum performance. Actually, give my current level of understanding of data handle, it is not clear to me that POINTER cannot be considered as |
Or in my example, a Python callback... i.e. it need not be data per se, we can misuse it to pass around functions and just do the casting in a VERBATIM block. In the future, there should probably be a dedicated POINTER type for this, but that's beyond the scope of this issue. |
I'm a lot more confused now, because it seems like
|
I looked at the translated dcdt.mod that began this issue and see that the last arg of
most of which are for RANGE variables, is
So I surmise that all of the special types that used to be in the dparam as well as the standard RANGE doubles that used to be in param, are now organized in one place. But from the <legacy?> threadargs definitions, the non-doubles are still separated into the
|
It seems to me now that the typical usage of POINTER, I.e, a double* to a RANGE variable, is presently fully functional except for an error message if invalid. Then the explicit check I added in the mod file would not be needed. Later on, for higher performance, the check could be avoided by a check for validity during initialize. I believe that one of the ways CoreNEURON has higher performance is that all model data is in a single array and thus a pointer to any range variable outside of the mechanism instance is merely an integer. In particular this includes Node* variables (such as voltage) and ionic variables that are used by the mechanism instance. For the future, it seems this could be effectively introduced into NEURON but I first have to look into how this is currently handled for voltage. |
This commit adds an example (by means of unit-tests) that demonstrates the behaviour we see #2458. It involves understanding how raw pointers and pointers to values inside a `soa` are function. It further demonstrates the difference of `generic_data_handle::get` and `generic_data_handle::literal_value`.
(Messages are crossing; but unfortunately I think the situation might be slightly more complicated. Hence I'm still posting despite the issue being "resolved".) I think I understand why the generated code uses When creating a Example, if a mechanism has a
one will find that the address So far it behaves exactly like we initially guessed. Interestingly, under these conditions the However, there's a twist. Namely code that assigns to
If we let
expands to
Since This is where
One imporant difference is that
correctly stores the address of |
This commit adds an example (by means of unit-tests) that demonstrates the behaviour we see #2458. It involves understanding how raw pointers and pointers to values inside a `soa` are function. It further demonstrates the difference of `generic_data_handle::get` and `generic_data_handle::literal_value`.
I have not fully parsed if there are any outstanding questions here, but I thought I would chime in with a few thoughts/comments/observations:
#define c *_ppvar[0].get<double*>()
#define _p_c _ppvar[0].literal_value<void*>()
As has I think been noted, if (as in the first case) the It's unfortunate that
In any case, At the risk of adding to the debt, I don't think there would be any technical barrier to adding |
That kind of mixing would definitely be a bug. My use of
That is certainly true. The nmodl translator correctly disambiguates, I believe, just by noting if It seems that Nevertheless, I do like the idea of new keywords/syntax that avoids the overloading. |
OK, I had assumed that this sort of introspection was beyond I would be inclined to modify the code generation to take advantage of this knowledge, and to generate, effectively, a
In the short term, I suppose that this is the simplest way forward. (apologies, I hit the wrong button and posted prematurely) |
This may be related to #2457 but I think it is different. Works for 8.2.2 (and earlier) but not master
To reproduce:
fails with
The text was updated successfully, but these errors were encountered: