How can I make this code work?
proc enumerableRepeat[T](value: T, n: int = -1): iterator(): T =
result = iterator(): T {.closure.} =
var i = 0
while n == -1 or i < n:
yield value
i += 1
proc writeFile[T](filePath,iter:iterator():T) =
var file = open(filePath,mode=fmWrite)
for str in iter: file.writeLine(str)
file.close()
writeFile("iter.txt",enumerableRepeat("a",100))
Try this fixed version:
proc enumerableRepeat[T](value: T, n: int = -1): iterator(): T =
result = iterator(): T {.closure.} =
var i = 0
while n == -1 or i < n:
yield value
i += 1
proc writeFile[T](filePath: string, iter: iterator():T) =
var file = open(filePath, mode=fmWrite)
for str in iter(): file.writeLine(str)
file.close()
writeFile("iter.txt", enumerableRepeat("a", 100))
OderWat,Thank you for editing the code :-)
And it should be a little slower
import times
import threadpool
{.experimental.}
var w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
var startTime = epochTime()
parallel:
for i,str in w:
spawn writeFile("dict_" & $i & ".txt",enumerableRepeat(str, 3_000_000))
echo "Time: ",epochTime() - startTime," seconds"
#Time: 2.846011525369249 seconds
than this?
proc writeFile2(filePath,text:string) =
var file = open(filePath,mode=fmWrite)
for str in 1..3_000_000: file.writeLine(text)
file.close()
var w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
var startTime = epochTime()
parallel:
for i,str in w:
spawn writeFile2("dict_" & $i & ".txt",str)
echo "Time: ",epochTime() - startTime," seconds"
#Time: 2.264008925878443 seconds
PS: I wanted to do something like how in C #
Parallel.For(0, 3, i=> {File.WriteAllLines(@"dict" + i + ".txt",Enumerable.Repeat(w[i],3000000));});
But there is a running total 00:00:01.1200015So why not using C# then? (evil smile)
Compiling with "-d:release" gives me "Time: 0.6296679973602295 seconds" (against about 2 seconds without it)
That is 0.77 using this exact code:
# nim c --threads:on --d:release
import times
import threadpool
{.experimental.}
proc enumerableRepeat[T](value: T, n: int = -1): iterator(): T =
result = iterator(): T {.closure.} =
var i = 0
while n == -1 or i < n:
yield value
i += 1
proc writeFile[T](filePath: string, iter: iterator():T) =
var file = open(filePath, mode=fmWrite)
for str in iter(): file.writeLine(str)
file.close()
var w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
var startTime = epochTime()
parallel:
for i,str in w:
spawn writeFile("dict_" & $i & ".txt",enumerableRepeat(str, 3_000_000))
echo "Time: ",epochTime() - startTime," seconds"
It may be possible to optimize it though :)
So why not using C# then? (evil smile)
C # is bound to NET platform. And this is his main, but in many cases - a significant minus. Nim - self-sufficient, self-contained - and that I like.
That is 0.77 using this exact code
I also compiled with the -d: release and --opt: size. Apparently, you have a much faster computer. I have a 4-core, but rather the old generation.
Ok. Let us assume that the code as fast as in C#. In addition, C # uses to restart the cached version of the program. I have run-time C # code is restarted. The first time it runs about 4 seconds.
Also, in terms of optimization just replacing:
for str in iter(): file.writeLine(str)
with
for str in iter(): file.write(str & "\n")
yielded a 1.3X speed-up (I.e., it took the time down to 0.14 seconds).cblake
I did not know that --opt: size so affects the speed. Now I will take this into account. Thank you. Replacing writeLine to write really accelerated the code is almost 1.5 times.
PS: Nim really fast. You just have to know how to use :-)
Modifying where the line ending is added can be even more optimized when you change the parameter to the iterator such that the string is only changed once. E.G.: enumerableRepeat(str & "\n", 3_000_000)
This would not even be faster if that was done more efficient than introducing a string copy.
That using WriteLine() is slower is a pity though. Here we see how simple things can change the outcome a lot. I wildly guess it calls "write()" twice, which is causing more overhead than the string implementation of Nim which copies the string to add the line ending.