Re: How to nimble test nested foldes?

2019-01-02 Thread kaushalmodi
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

2019-01-02 Thread kaushalmodi
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

2019-01-02 Thread cblake
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

2019-01-02 Thread jegfish
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

2019-01-02 Thread moerm
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

2019-01-02 Thread cblake
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

2019-01-02 Thread cblake
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

2019-01-02 Thread dom96
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

2019-01-02 Thread moerm
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

2019-01-02 Thread Stefan_Salewski
> 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

2019-01-02 Thread rayman22201
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

2019-01-02 Thread moerm
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

2019-01-02 Thread Jehan
@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

2019-01-02 Thread lqdev
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

2019-01-02 Thread lqdev
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

2019-01-02 Thread Stefan_Salewski

alloc(sizeof(ptr MyObj))


Run

seems to be a typo. Guess it should be alloc(sizeof(MyObj))


Re: Use GC_ref on a pointer

2019-01-02 Thread moerm
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

2019-01-02 Thread LeuGim
@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

2019-01-02 Thread LeuGim
> 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

2019-01-02 Thread lqdev
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

2019-01-02 Thread e
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

2019-01-02 Thread Araq
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

2019-01-02 Thread Araq
> 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

2019-01-02 Thread moerm
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

2019-01-02 Thread LeuGim
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

2019-01-02 Thread tim_st
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?

2019-01-02 Thread novikov
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

2019-01-02 Thread cblake
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

2019-01-02 Thread liwt31
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

2019-01-02 Thread lqdev
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

2019-01-02 Thread tim_st
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

2019-01-02 Thread juancarlospaco
`{.inline.}` and `uint` ?.


Re: [help needed] nim version of: COMPARING PYTHAGOREAN TRIPLES IN C++, D, AND RUST

2019-01-02 Thread moerm
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

2019-01-02 Thread mratsim
Create a doWhile template?


Re: Nim vs D

2019-01-02 Thread wadesteve
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

2019-01-02 Thread wadesteve
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

2019-01-02 Thread Araq
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

2019-01-02 Thread juancarlospaco
`markAndSweep` ?.