Re: How to nimble test nested foldes?
You can create a `task` in your nimble file. I do that in my `config.nims` file, but the same should work in your .nimble too. Ref: [https://github.com/kaushalmodi/nim_config/blob/ffdefa859b9b9837dcb8fe643f04a75e5f98089b/config.nims#L239-L247](https://github.com/kaushalmodi/nim_config/blob/ffdefa859b9b9837dcb8fe643f04a75e5f98089b/config.nims#L239-L247)
Re: it is hard to load forum.nim-lang.org for months
Nim Forum loads fine on the latest Firefox versions for me on Win 10 and Android.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
Those are all fine points. Asm can sometimes make a bigger difference than people conditioned to not question compiler output expect (and there are many such people). This is especially with vector units. A few years back, I wrote an AVX2 vectorized "minimum" function that ran 24x (twenty four times) faster than a C one. That's a much bigger time ratio than most "typical use" comparisons of _many_ programming language pairs (though obviously most programs do more things than compute minima). Auto-vectorization in gcc (at least) has gotten better since for that precise problem, though it can still miss many opportunities. If you ever do need to write asm, those "intrinsics functions" like `_mm256_add_ps` (there are a hundred others) are often an easier entry point/way to integrate with your program than raw asm/`.s` files. You can use them from Nim, too. :-) See, e.g., [https://github.com/numforge/laser](https://github.com/numforge/laser) README/code/etc. for how to use SIMD intrinsics.
Re: Default value for missing JSON fields
Could you (or anyone else) please provide guidance as to what I could do to preserve an easy to use interface for users of my library? Currently I have 2 ideas. * The first is to define types with the appropriate private fields for the JSON and defining exported getter procedures for people importing the module. * The other is to define custom procedures for converting the JSON to Nim objects. Currently I am leaning towards the second because I think truly accessing fields feels better than replacing them with procedures, but I am not experienced enough in Nim or programming in general to know if there may be harmful effects of either possibility, or if there may be other options.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
We are in agreement if I understand you correctly. I don't care whether Nim code runs 0.5% or 3% slower than C code. In fact, I think that whole benchmarking is irrelevant except for a rough overview ("Nim is within x% of C's speed"). Reason (and C/C++/D developers might want to read this carefully): Looking at the code created by - even very good - C compilers everyone with some not insignificant knowledge of ASM will concur that developing in ASM is the way to get the fastest code. Unfortunately though, ASM (next to some other issues like portability problems) also has the major disadvantage of being ridiculously far away from the problem domain. So, if we were serious about it we needed to make my axis longer to fit ASM quite a bit beyond C, at the extreme end of runtime speed but also extreme distance to problem domain. In other words: If we _really_ were obsessed with runtime speed we should chose ASM over C - but we don't, i.a. because we would pay with a very significant increase in development time, more and more difficult to spot bugs, etc. So the reality is that C developers already made a compromise trading development speed for runtime speed. Nim developers do the same - but with a much, much better deal; we get a ton of lower dev. time, fewer bugs, etc. for what in the end is a ridiculously low runtime price even if it happened to be 5% less speed than C. And btw - albeit largely theoretically right now (I assume) - we even _could_ compensate and reach C's RT speed due to Nims compiler having much more information than a C compiler (almost always has) due to factors like e.g. Nim strong static typing which allow the Nim compiler to generate C code that then again would allow the C compiler to create faster code.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
Also, I guess a TL;DR part C) - I was never arguing against the tautology that a faster algorithm is faster. That is kind of a weird straw man position. No idea how quoting 600 microseconds for it left that impression, but maybe bears correcting the record. (I didn't assess correctness, though perhaps I should have. To me that whole algo area is besides the point of the prevailing discussion of an artificial benchmark. I never need Pythagorean triples, myself.)
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
Oh, I got your point and tried to emphasize that. I wasn't arguing against you anywhere that I know of. I totally agree with your a,b,&c. I suspect we don't disagree on anything real at all, but are just discussing different aspects. I tried to express praise for your approach (if you happened to need to do this _particular_ thing) and gave a reference link. :-) Please note that nothing I say below should be taken as any specific rebuttal to something you said. My point was less about exactly zero vs non-zero abstraction cost (I even noted my own 5% variation) and more about the cost being very sensitive to compilation strategy, PGO as a particular example. I would say, looking at the generated C code, that this is not much about "Nim language iterator overhead aka 'cost'" and more just about "C compiler assembly code generation variability". That's an important distinction as slowness does not necessarily translate into "work for Nim core to improve anything". Backends vary and could change a bunch of stuff and be different in the next version of gcc/clang/whatever, for example. So, Nim kind of needs to target a "broad cross section" of what works well on the various backends, not overfit to one. (Not saying you said otherwise, just backing up importance of the distinction.) You mentioned compiling my code on Ryzen, but not using gcc's PGO. PGO is mostly just a very strong version of your (c) hints idea where the compiler generates extra code to measure what it thinks will help it make better code generation decisions. (Yeah, a person or some GA picking optim flags/luck/etc. could all still maybe do even better sometimes as I already alluded to, but at ever increasing developer costs.) To add a little more color quantitatively, I just did the same PGO experiment with the same version of gcc on a Ryzen 2950X clocked at 3.80 GHz and saw times go from 140 ms down to 85 ms..(best of 10 trials for both). That's not quite the same 2x speed-up as for the Intel case. Yeah, maybe Ryzen has better CPU predictors or predictor warm-ups or maybe it gets a bit luckier with "non-PGO" -O3 yadda-yadda defaults, etc. Whatever the causes, 1.65X is still a lot more than PGO boosts I usually see of 1.05x to 1.15x (such as with your algo, for example). { Of course, the boost is still not as good as a better algorithm. I never said so, nor meant to imply it. If a better algo is handy and speed matters then by all means use it! At least some of the time, a better algo will not be as easy to come by as PGO. } Anyway, I realize that it's a tangent from your original interest in this problem, but if you're as serious about (c) as a general guideline as you seem, and if you haven't already, then you should look into PGO sometime. My bet is that for this problem and for most backend compilers that a PGO Nim would be faster than non-PGO "pure C". Even though such a goal is explicitly _not_ your objective, I think it's still interesting. Nim is one of the very few languages I've tried that in "typical" practice is often "about as efficient as C" (with all the usual disclaimers as to algos, etc.) PGO can also be very little developer time extra cost. Once you get a little script set up, you just type `nim-pgo pythag './pythag > /dev/null'` for some `pythag.nim` file instead of `nim c -d:release pythag.nim`. If the program had less output (say the sum of the c in c^2=a^2+b^2) the shell IO re-direct wouldn't even be there. For this program, it took me almost no time to try PGO. And, of course, YMMV - that 2x on i7-6700k effect is among the biggest PGO boosts that I've ever seen. That seemed noteworthy. So, I noted to y'all. :-) In terms of comparing Ryzen timings, running in a VM should not make much difference on this problem as it is a pure user-space CPU hot loop except for the time queries..That's really a best case scenario for VMs. Of course, if your host OS is time-sharing the CPU between your VM instance and some other process then that could slow things down a lot - arbitrarily much, really if the host OS is overloaded. Might help to take the minimum time out of more trials. You should be able to get 100..200 ms of one core all to yourself at _some_ point. :-) My guess is that you could get that 210 ms down to under 100 ms (not that it really matters for anything practical in this exact case. A better algo is better, but a lot of people - not just in this forum - are, rightly or wrongly, discussing this problem in the context of "programming language performance" which is the only reason I bothered to write both of these posts. The clang/ldc/rust/etc. numbers were all more closely clustered than 1.65x of the Ryzen PGO experiment in Timothee's very first link (217 ms/153 ms = only 1.42x). TL;DR - A) For this problem, compiler back-end generation effects dominate Nim front end overheads (and possibly front-end overheads for other languages) for which the huge PGO boo
Re: it is hard to load forum.nim-lang.org for months
I've never had any problems (and it seems others don't either) so it's really hard for me to troubleshoot this, if this happens again check your browser's Developer Tools to see what response the forum is giving or run `curl -vL forum.nim-lang.org` and show us the output.
Re: Use GC_ref on a pointer
Yes and no. Yes, you are right, I had a wrong (and since then corrected) statement in my post. And yes it does work but it's almost certainly not what he wanted anyway (and a weird way). But yes, I got confused myself.
Re: Use GC_ref on a pointer
> there are multiple problems. For one result[] = newMyObj() says "return what > result points to" which however is not a pointer. More gravely though, even > if it worked you would lose the just allocated pointer/memory because you > would overwrite result with what MyObj() returns. I do not really think so. result[] = newMyObj() Run does copy the CONTENT of newMyObj() into result variable. So when he allocates mem for result in a correct way with alloc() (I mentioned the sizeof bug) he should have a valid pointer initialized to valid content, for example with x == 42. Of course he is responsible for deallocation of that object.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
My understanding of the original article was that it was about elegant abstractions and their costs. IMO Nim really shines here. This thread shows how low cost iterators really are in Nim. They are far cheaper in Nim than I thought they were. Kudos to the Nim core team! @moerm also shows a tangential super power of Nim, which is that you not only get very low cost high level abstractions, you have enough expressiveness to do optimizations on par with C when you need to.
Re: Use GC_ref on a pointer
Yes and no. Yes insofar as you can of course allocate whatever you please and pass those pointers around and/or use them. No insofar as you must be careful to not wildly mix up Nim-allocated objects and pointers. In your example proc newMyObj(): MyObj = result = MyObj(x: 42) proc allocMyObj(): ptr MyObj = result = cast[ptr MyObj](alloc(sizeof(ptr MyObj))) result[] = newMyObj() Run there are multiple problems. For one `result[] = newMyObj()` says "return what result points to" which however is not a pointer. More gravely though, even if it worked you would lose the just allocated pointer/memory because you would overwrite `result` with what `MyObj()` returns. What you actually wanted is probably this: proc allocMyObj(): ptr MyObj = result = cast[ptr MyObj](alloc(sizeof(MyObj))) result[].x = 42 Run Alternatively you could also use your `newMyObj()` proc _instead_ of `allocMyObj()` but then your object were a Nim (allocated) object and taking its address to have a pointer to pass around (to C code) would risk to end in a weird situation because from Nims point of view _it_ is in charge of that object while from C's point of view it could do with that pointer whatever it pleases and assume its - not guaranteed - existence etc. Maybe the following code can help you to see what I mean type MyObj = object x: int proc newMyObj(v: int): MyObj = result = MyObj(x: v) proc allocMyObj(): ptr MyObj = result = cast[ptr MyObj](alloc(sizeof(MyObj))) var tmp = newMyObj(42) # under the hood a Nim ref echo "tmp: " & tmp.repr() & "tmp address: " & repr(tmp.addr()) # show it from Nim's point of view echo "allocated object: " & result.repr() # now show the alloc'd object result = tmp.addr() # but return the other one bc. result has been overwritten # -- main -- let mo = allocMyObj() # the allocated object is lost. We have no way to access or free it echo "After allocMyObj(): " & mo.repr() mo.dealloc() # deallocates which one? Obviously *not* the alloc'd one let mo2 = newMyObj(43) # try it the other way echo "After newMyObj(): " & mo2.repr() Run
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
@moerm: Your algorithm uses Euclid's formula, which (1) does not exhaustively enumerate all non-primitive Pythagorean triples (for example, it'll skip 9^2+12^2=15^2) and (2) does not enumerate them in the same order as the original algorithm. To get that right, you have to jump through a few additional hoops. I threw [this D code](https://run.dlang.io/gist/rbehrends/1911c4c30143b015a15032e69808000c?compiler=ldc&args=-O2) together a couple of days ago as a proof of concept, which is a bit more complex, but matches the output of the original implementation exactly. It should be pretty trivial to port to Nim for anybody who is interested. It will still beat the pants off the original, simply because that's what happens if you compare an O(n log n) time complexity algorithm to an O(n^3) one. @cblake: Yes, the original blog post is about the cost of abstractions (or rather, being able to avoid that). However, once you're dealing with double or triple nested loops, algorithmic optimization compared to compiler optimization begins to dominate, because the constant factor that compilers can give you quickly becomes secondary for O(n^k) time complexity with k >= 2. (I could write Ruby or Python code that would beat the C++ implementation for not very big values of _n_ ), and the composability of iterators/ranges is not adequate for the most interesting algorithmic optimizations.
Re: Use GC_ref on a pointer
Oh, of course! That was a mistake on my behalf, but also part of what I wanted to do – I wanted to allocate some memory to store a pointer, but storing the struct itself seems like a better idea.
Re: Use GC_ref on a pointer
Well, maybe instead of asking you to solve my problem let me ask a more general question about pointers: From what I understand, `ptr T` is untracked by the GC. So can I just do something like this? type MyObj = object x: int proc newMyObj(): MyObj = result = MyObj(x: 42) proc allocMyObj(): ptr MyObj = result = cast[ptr MyObj](alloc(sizeof(ptr MyObj))) result[] = newMyObj() Run Or will this cause some sort of memory problems? I'm asking this question because I'm not very experienced with such low-level programming, and my application uses pretty much what I've shown in the example (except `alloc()` isn't used directly, but it more or less resembles what I'm doing in my code)
Re: Use GC_ref on a pointer
alloc(sizeof(ptr MyObj)) Run seems to be a typo. Guess it should be alloc(sizeof(MyObj))
Re: Use GC_ref on a pointer
The way you asked your question (hint: vague, general, not clear what you really want) Araq responded perfectly correctly. Now you ask us to read a 150 lines file and we are supposed to find out what you want and what your problem is by reading through and make sense of your code.. Chances for that to happen are slim I guess. Maybe helpful: Sometimes C stuff wants/needs some structs and stuff allocated by a caller. In such cases it's often better to do those allocations in C and to pass them to Nim in a way where the Nim code doesn't need to know anything about them (other than that they are pointers of some kind). As long as the Nim code doesn't need to do anything with those pointers (other than passing them around) you need _not_ be precise; you can, for instance, tell Nim that some pointer to some is simply a char pointer. Another maybe helpful hint is to "allocate" _simple stuff_ (like say a C char array) in Nim (by simply having a var) and to pass the pointer to it (more precisely usually a pointer to its data) via myvar.addr() to a C function. Do **not** allocate a bit here (Nim) and bit there (C) but try to be consistent. For a more specific answer you need to provide a more specific problem description.
Re: Type instantiation for `==` func
@e: To make it work `node != nil` in `contains` (`bbtree.nim#612`) needs to be changed to `not node.isNil`. It's used from both `==` and `<=`, error messages hint to that.
Re: Type instantiation for `==` func
> if it's that obvious What looks obvious is that error is not because of procedure's name (`==`) - you may test it with changing it to some different name. `len` \- yes, it's in the library, I didn't see the librarythen, tried the snippet from the original post. Trying the library itself, errors are identical for `<=` and `==`. I don't see connection to your issue.
Re: Use GC_ref on a pointer
I need to pass around some data between Nim and C, and this `someCAllocFunction` returns a void pointer. I tried casting it to a `ptr MyType` and setting its value using `point[] = MyType()` (in reality I'm using an object with some fields, and the object is initialized in a separate function). But then, in a callback I passed to C, I'm trying to access my data again, but a `SIGSEGV` is raised. instance of TestAutowrenType Traceback (most recent call last) autowren.nim(143)autowren autowren.nim(136)w_data= autowren.nim(130)data= gc.nim(289) unsureAsgnRef gc.nim(185) decRef SIGSEGV: Illegal storage access. (Attempt to read from nil?) Run Here's the source code of my program: [https://github.com/liquid600pgm/rapid/blob/master/src/scripting/autowren.nim](https://github.com/liquid600pgm/rapid/blob/master/src/scripting/autowren.nim) I understood this as the GC removing my object while it's passed around in C code, and that's why I wanted to mark it as referenced.
Re: Type instantiation for `==` func
So, digging deeper, the place where the generic instantiation is losing is while curr != nil or stack.len > 0: Run So, the compiler can't infer a type for nil. It hadn't occurred to me to look for !=. If I replace that line with while (not curr.isNil) or stack.len > 0: Run and do the same thing in several other places, the problem goes away. So, it does have to do the function's name, and the semantics of == and !=. No compiler bug. Thanks for your help.
Re: Use GC_ref on a pointer
Achieve what? It's a `ptr`, the GC doesn't care about it, it won't be deallocated for you.
Re: When's GCunref() necessary
> dest not on stack and src is not nil, so ref is increased? Hmm, that's a good point. I need to think about this. > Is it legal to continue to use x? Yes.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
I fully agree on Nim indeed _being_ a good language. My point though wasn't "I can do faster code than ...". My point was that one should a) _think_ about optimization starting from "what's actually the point and what's the bottleneck or the most promising approach?" (in this case it was "use a better algorithm") and also "how much optimization do I need and what is it worth? (e.g. in dev time)", b) avoid _obvious_ problems (like nesting loops without need), and c) _help_ the compiler by providing clear hints. I also copied your code verbatim (modulo the now(); I prefer my own routine because I know it's directly getting the monotonic clock), compiled it with the exact switches used by timothee and the above code from you took around 210 ms on my system (debian, Ryzen (in a VM), gcc 8.2.0). And I'm not surprised. While you are right and Nim has excellent iterators the basic problem still is 3 loops and an if in the inner most loop (and a bad algo). Maybe my Ryzen is a bit more or a bit less sensitive than your CPU in that regard but any kind of branching (loops, ifs) risk to trash the L1 and often enough L2 too. And btw, Nim's iterators, as great as they are, are not zero cost. One single change in your code, namely replacing `for z in toInfinity(1):` with `for z in 1 ..< 0x7FF:` made the code run almost 10% faster. But I had another interesting point in my first post: Why use _any_ language XYZ? Why not use, for instance, Python? What's the point, the difference? (Looking from the perspective I'm interested in here) the answer is: Python means "way less dev. time than C but way slower code (runtime)". Where is Nim on that axis? _That_ (imo) is an immensely important point and one where Nim really shines: You get a dev. time not far from Python -and also- a run time very close to C. That's why I do not even _expect_ and desire Nim to ever reach 100% of C code (runtime) speed. What I want is a language that makes it easy to think about and focus on my task, the algorithm and still get near C speed. From what I see nobody and nothing gets even close to Nim in that crucial point that is _directly related_ both to productivity and code quality and I still _can_ profile and optimize real hot spots in C.
Re: Type instantiation for `==` func
But error message clearly says that you have no `len` procedure for `BBTree`. Just define it. Or maybe you meant to use `size` field in `BBtree` for that. You may after all rename `==` to whatever else (some `^&%`) and see the error message not changing - it has nothing to do with the function's name, just with its content. > Even if I make the bodies of the two functions identical, Nim still gives an > instantiation error for the second one. No, it doesn't.
Re: Type instantiation for `==` func
There is a len func func len*[K,V](root: BBTree[K,V]): int = ... but the compiler doesn't match it similiar to this issue [https://github.com/nim-lang/Nim/issues/9606](https://github.com/nim-lang/Nim/issues/9606) . I tried the code by explicitly call filename.len to force the correct match, but still other errors appear, if it's that obvious, please show your working solution.
How to nimble test nested foldes?
Is it possible to configure **nimble** somehow so that it runs tests in nested folders as well?
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
Every language has nested loops. My view is that the original article about C++20 ranges conceived this test/benchmark to be about the cost, if any, of abstractions, not exactly the performance of "nested loops however you write it" as suggested by Timothee's code or "the fastest algorithm for generating Pythagorean triples" (see [https://en.wikipedia.org/wiki/Pythagorean_triple](https://en.wikipedia.org/wiki/Pythagorean_triple) for an explanation of moerm's much better algorithm - you should definitely use something like moerm's algo _if you actually had a need for many triples_ for some reason). A lot of what is creating variation in results here, and why I am posting this reply, is that this particular case is more sensitive than most to compiler optimizations and assumptions/code layout, etc. With the below program, I got a full 2.02x speed-up using gcc's profile-guided optimization (145.0 ms to 71.8 ms; both best of 10 trials on a i7-6700K at 4.85 GHz on Linux, gcc-8.2.0 with Gentoo patches rev6). Usually, I only get 1.10x to 1.15x speed-ups. Thus, this case is more sensitive to optimizations. iterator toInfinity(n=1): int = var z = n while true: yield z inc(z) iterator triples(n=1000): array[3, int] = var i = 0 block all: for z in toInfinity(1): for x in 1 .. z-1: for y in x+1 .. z-1: if x*x + y*y == z*z: yield [x, y, z] inc(i) if i == n: break all import times proc main() = let t0 = now() for triple in triples(): echo triple echo now() - t0 main() Run When Timothee's current code is instrumented with `times.now()` and not compiled with PGO it is 1.5x faster than the above program (96 ms). When both programs are similarly compiled with PGO the performance basically matched to almost within measurement error (68.13 ms best of 10 trials, but noise/range over those trials was over 2 ms). (All I did was fiddle with the loop ranges.) In other words, Nim's iterators seem to be a zero cost abstraction, as advertised, at least when compiled with PGO on gcc in this use case. This also makes sense if you look at the C code Nim generates -- just 3 nested loops anyway. Maybe one could pick nits that 71.8 vs 68.13 is not quite zero. Fair enough, but 5% is much less than the 2x variation sensitivity from PGO. Heck, given the giant 2x sensitivity, one of those "genetic algorithm to optimize the optimization flags" approaches could probably do even better than PGO and have the two Nim versions jockey back & forth for fastest. Looking at the generated C code, that seems likely to me. The point of this post is that in this case, compilation strategy/optimization options matter more than people might expect (though several commenters did sort of seemed to know that already). For the curious, moerm's better algorithm with PGO runs in just 600 _microseconds_ on the same machine, and 680 microseconds without PGO, a more typical 1.13x factor, and much smaller than just using a better algo. Personally, I think that it might be a little nicer to be able to `return` to exit iterators rather than using the `block all: ... break all` construct. I could see bug-finding arguments (iterators != proc/func) for not allowing that, though. Anyway, I think Nim mostly wins (or at least ties) in the "elegance contest" here. Also, for anyone trying to reproduce these effects/do profile-guided-optimization with Nim in general, the way I drive my PGO compilation is with a script that boils down to: nim c -c -d:r PROG.nim $cc -fprofile-generate $nimcache/r/PROG/*.c -o PROG ./PROG $cc -fprofile-use $nimcache/r/PROG/*.c -o PROG Run You may also need some `-O3 -fwhole-program, -flto, -march=native` in that `$cc` variable, and definitely need at least `-fno-strict-aliasing`.
Re: When's GCunref() necessary
Thanks. But I'm still under the impression that `d.s = "abc"` increases the ref count of `"abc"`. If I understand correctly `d.s = "abc"` will lead to the execution of the following function: proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} = # unsureAsgnRef updates the reference counters only if dest is not on the # stack. It is used by the code generator if it cannot decide wether a # reference is in the stack or not (this can happen for var parameters). if not isOnStack(dest): if src != nil: incRef(usrToCell(src)) # XXX finally use assembler for the stack checking instead! # the test for '!= nil' is correct, but I got tired of the segfaults # resulting from the crappy stack checking: if cast[int](dest[]) >=% PageSize: decRef(usrToCell(dest[])) else: # can't be an interior pointer if it's a stack location! gcAssert(interiorAllocatedPtr(gch.region, dest) == nil, "stack loc AND interior pointer") dest[] = src Run `dest` not on stack and `src` is not nil, so ref is increased?
Use GC_ref on a pointer
I have a type stored in C, that's a pointer to a type. type MyType = object var point = cast[ptr MyType](someCAllocFunction(sizeof(ptr MyType))) GC_ref(point) # this doesn't work, because GC_ref expects a ``ref T``, ``seq[T]``, or ``string`` Run How can I achieve this?
Re: Type instantiation for `==` func
I replaced some generic parameters in your code with untyped templates and then always new errors appeared in procs that were called from the proc that showed the error, so it seems you have somewere the real bug, but the compiler can't show you the correct place (I've seen this behaviour before when generics are used in code I have written). I couldnt find out the exact place because nim and nimsuggest got into endless loops at 100% cpu when replacing the second proc with untyped template. The following shows that normally your generic type idea works (and I think it's a good idea how you have written your code): type GenericType[K, V] = object key: K value: V func values*[K,V,T](t1: GenericType[K,V], t2: GenericType[K,T]): tuple[v1: V, v2: T] = result = (t1.value, t2.value) when isMainModule: var t1: GenericType[string, int] var t2: GenericType[string, char] t1.key = "abc" t1.value = 1 t2.key = "abc" t2.value = '1' var v = values(t1, t2) echo v.v1 echo v.v2 Run So for now I can only suggest when you use generics test your procs as soon as possible, because generic procs are often checked very late by the compiler which means that some incorrect procs only error when they are actually called in the code :(
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
`{.inline.}` and `uint` ?.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
For what it's worth: I c2nim'd the simple.cpp and slightly adapted it to have a `limit` parameter to (using `i`) limit the number of computed triples. Compile time on my Ryzen box and using gcc as the backend was around 1.6s the first time and about 0.25 s for following runs (said Nim). Execution time of the release compiled code was about 220 ms. My main motivation was to follow a hunch, namely that this isn't about generators, lambdas or whatever but about a) a very poor algorithm (no surprise there; after all it's even called "simple" (as in "naive" I presume)) and b) careless loop nesting. One of the major rules wrt performance is to be careful with loops. Another rule is to help the compiler by good hinting. So, using a better algo plus having only 2 loops (and using a microsecond timer rather than crude `time` for measurement) I arrived with the following which (release mode) does the job - incl printing! (which amazed me. Kudos to the Nim team!) - in about 2 ms. const plimit = 1000 # how many triplets to compute (1000 like in the blog code) proc pyth3s(limit: int) = var found = 1 var m: int = 2 while true: var n: int = 1 while n < m: let m1: int = m * m let n1: int = n * n let c: int = m1 + n1 let a: int = m1 - n1 let b: int = (m * n) shl 1 echo $a & ", " & $b & ", " & $c if found >= limit: return found.inc n.inc m.inc let t0 = getHRtime() # microsecond timer pyth3s(plimit) let t1 = getHRtime() echo "Done. First " & $plimit & " pyth. triplets computed in " & $(t1 - t0) & " musec" Run Thoughts: Obviously reducing the loops to 2 is a _very major_ performance improvement. But I think (might be wrong) that explicitly introducing `m1` and `n1` is helpful as a hint to the compiler. Moreover limiting the use of vars to the reasonable minimum and to prefer `let` plays on one of Nims strengths. Yes, the code _looks_ longer but wrt performance the decisive factor isn't how it looks to a human but what the compiler can make out of it.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
Create a doWhile template?
Re: Nim vs D
The process where it will be going to provide the perfection for the user to proceed it. So this will be taking guided by the https://epsonsupports.net/blog/epson-printer-not-printing/";>epson](https://epsonsupports.net/blog/epson-printer-not-printing/";>epson) printer not printingfor finding the valuable work which will be going to acquire the part.
Re: Nim vs D
The process where it will be going to provide the perfection for the user to proceed it. So this will be taking guided by the https://epsonsupports.net/blog/epson-printer-not-printing/";>epson](https://epsonsupports.net/blog/epson-printer-not-printing/";>epson) printer not printingfor finding the valuable work which will be going to acquire the part.
Re: When's GCunref() necessary
The manual is completely wrong here. `GCunref` needs to be paired with `GCref`, always. And indeed you need the GCref in order to keep the GC from collecting the string too early.
Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST
`markAndSweep` ?.