freenode/#sicl - IRC Chatlog
Search
7:20:43
beach
Today is a bit complicated. I have an appointment at 9 which is only 5 minutes from here, but there is a general strike which means less public transportation which means more traffic jams. I could take my bicycle, but I need to be back here for physical therapy at 9:30, and if I take my bicycle, I will come back sweaty and I will need a shower, which there is no time for.
7:22:03
beach
So I am going to leave by car very soon, just to see how the traffic situation looks. If it looks too bad, I'll come back and switch to bicycle.
7:23:13
beach
Driving always takes longer, because it is unpredictable how much time it will take, so one has to have significant margins. Bicycle is always predictable.
14:37:56
beach
alandipert: I lied to you the other day. The expression is (function (lambda (x) (cleavir-primop:car x))). And I managed to "manually" get to the nested function. Here is the essence of it: metamodular.com/mir.png
14:38:50
beach
The left column of the lower block, except for the last 3 instruction, is a call to ERROR when too few arguments are given.
14:39:21
beach
The right column of the lower block is a call to ERROR when too many arguments are given.
14:39:51
beach
The middle column and the last three instructions to the left is the body of the function.
14:41:01
beach
Most of those operations just access cells in the static environment, like to get to the ERROR function or its constant arguments.
14:41:53
beach
But the UNSIGNED-SUB in the middle column and the MEMREF1 at the end of the left column compute the body of the function.
14:44:38
beach
The layout that the visualizer computes is not optimal, but if you know what to look for, it is not too bad either.
14:45:58
beach
So one does not have to follow the dotted lines manually. They get highlighted by these functions.
14:50:51
beach
So for instance, if you want to track what happens to the argument, you can do this: metamodular.com/mir2.png
14:52:13
beach
X is copied to a lexical variable, then 1 is subtracted from it, removing its tag. Then the resulting address is used in a MEMREF1 instruction, with the result in another lexical variable which is ultimately returned.
14:56:21
Bike
making parts of the sequence machinery will probably cause weird metacircularity problems, since clos uses sequence functions. i'll have to put in some thought there
14:56:51
Bike
of course in most of those cases the types of the sequences can be known at compile time, so i could maybe dodge it, but that's not very elegant unless it's the compiler working it out
14:57:54
beach
I keep thinking thoughts like that as well, but I think there is less risk than one might fear.
14:58:41
beach
CLOS probably uses sequence functions only with standard types, so if the functions are properly satiated, there should be no problem.
14:59:24
beach
That's how I arrived at the conclusion the other day that SICL could very well make CAR a generic function.
14:59:52
Bike
you're right in principle, but i think clasp might invalidate generic functions more than sicl does. i'll have to try it and if i'm right, maybe have it not do that
15:00:52
beach
Then the discriminating function is computed from the call history without the use of generic functions.
15:01:21
beach
So as long as you don't remove valid call-history entries when you invalidate, you should be fine.
15:01:23
Bike
clasp is careful about the call history but i think less careful about keeping the discriminating function in place. correct me if i'm wrong - in sicl when you hit dispatch-miss, it computes a new discriminating function immediately?
15:02:00
beach
No, I believe it sets the discriminating function that will compute a new one from the call history.
15:02:51
Bike
i mean basically i'm worried that the "without the use of generic functions" part is going to get more difficult the more things are generic.
15:02:53
beach
I do that to avoid recomputing discriminating functions that may never be used because of multiple successive changes to the methods and such.
15:04:57
beach
If CAR is satiated and its discriminating function is computed and never invalidated, it works like an ordinary function.
15:05:22
Bike
well, i mean. let's say FIND is generic, and in such a way that the user can specialize the sequence (for their own types). They do so and call FIND. FIND is invalidated. When the invalidated-discriminating-function is called, we have to compute a new discriminating function, but if while doing so we call FIND there is a problem.
15:06:42
beach
Yes, I see. There could be cases like that. If so, you had better compute the discriminating function immediately.
15:08:45
beach
I think I am trying to say that there are ways out of this problem that are not too complicated, and things are not as bad as the AMOP says if you are a bit careful.
15:09:37
Bike
in addition to the compiler, clasp has "interpreted" discriminating functions, which are closures that use the dtree directly. if we put an "interpreted" discriminating function in place before compiling a new discriminating function, we should be able to call the function at issue while computing its new discriminating function
15:10:00
Bike
then we just have to compute the dtree without calling generic functions... which may still be difficult, but it's a whole lot less code to worry about than the compiler
15:11:26
Bike
anyway, yeah, i'll try all this out and tell you how it goes. i think the sequences extension is a natural fit when you have fast dispatch
15:12:53
beach
I think that if the sequence has at least a few elements in it, then the guts of the computation is going to dominate over the dispatch cost.
15:13:30
beach
This is just gut feeling of course, and it would have to be metered for more certainty.
15:16:27
Bike
well, i think you're right. i've been getting appreciable speed improvements but with sequences at least a few hundred long.
15:16:43
Bike
it lowers to MIR, but the MIR might be kind of anodyne compared to everything sicl does, i don't know
15:17:47
Bike
ome things i wasn't sure (and am still not sure) how to lower very well, like aref-instruction
15:18:39
Bike
MIR doesn't have a memref instruction that can handle aref, or it didn't when i was worrying about this months ago
15:19:25
Bike
the address is something like base + constant_shift * index, base and index being variable
15:20:03
beach
Ah, I see. I just emit several instructions. I was convinced by scymtym that "tiling" could fix this later.
15:21:20
beach
Also, I count on AREF being done in a loop, so that most of that stuff is loop invariant.
15:24:22
beach
Now that I have a reasonable visualizer (that can be improved) and I am working on MIR myself, I personally think that I can more easily spot opportunities for optimization.
15:24:48
beach
For instance the obvious thing that all cells are accessed right after the ENTER, whether they are needed or not.
15:26:17
Bike
right... i guess rather than the dominator, what you could do there is put it just before uses, and then use other optimization passes to lift the fetch out of loops and stuff
15:27:04
beach
Yes, I mentioned that the other day. Loop invariant stuff and redundancy analysis (of which there are several types).
15:28:13
beach
We are going to need such optimizations anyway, so I am happy to wait for them to exist. :)
15:29:28
beach
And, as we know, redundancy analysis must be done carefully. These days, it can be cheaper to recompute than to store.
15:31:52
Bike
i guess that's where those detailed block frequency metrics like llvm has would be nice. to put a number on how much a given basic block is executed, i mean
15:32:53
beach
Sure. I am a bit cautious about using data gathered from execution, but certainly taking "probabilities" into account would be good.
15:33:02
beach
I guess my (possibly erroneous) thinking here is that, once I get something simple working at all, there might be some additional interest from more people to help improve things.
15:34:17
beach
I necessary condition for that to happen is maintainable code and good documentation, which would be my main task.