Re: Help optimizing code?
On Tuesday, 2 January 2018 at 07:17:23 UTC, Uknown wrote: [snip] 0. Use LDC. It is significantly faster. 1. Utilize the fact that the Mandelbrot set is symmetric about the X axis.You can half the time taken. 2. Use std.parallelism for using multiple cores on the CPU 3. Use @fastmath of LDC 4. imageData.reserve(width * height * 3) before the loop 5. [1] is a great article on this specific topic [snip] Forgot to mention that since you already know some of the edges, you can avoid unnecessarily looping through some regions. That saves a lot of time
Re: Help optimizing code?
On Monday, 1 January 2018 at 15:09:53 UTC, Lily wrote: I started learning D a few days ago, coming from some very basic C++ knowledge, and I'd like some help getting a program to run faster. The code is here: https://github.com/IndigoLily/D-mandelbrot/blob/master/mandelbrot.d Right now it runs slower than my JavaScript Mandelbrot renderer on the same quality settings, which is clearly ridiculous, but I don't know what to do to fix it. Sorry for the lack of comments, but I can never tell what will and won't be obvious to other people. Hey! I happened to also write a Mandelbrot generator in D. It was based of the version given on rossetacode for C[0]. Some of the optimizations I used were: 0. Use LDC. It is significantly faster. 1. Utilize the fact that the Mandelbrot set is symmetric about the X axis.You can half the time taken. 2. Use std.parallelism for using multiple cores on the CPU 3. Use @fastmath of LDC 4. imageData.reserve(width * height * 3) before the loop 5. [1] is a great article on this specific topic For reference, on my 28W 2 core i5, a 2560x1600 image took about 2 minutes to render, with 500,000 iterations per pixel. [2] is my own version. [0]: https://rosettacode.org/wiki/Mandelbrot_set#PPM_non_interactive [1]: https://randomascii.wordpress.com/2011/08/13/faster-fractals-through-algebra/ [2]: https://github.com/Sirsireesh/Khoj-2017/blob/master/Mandelbrot-set/mandlebrot.d
Re: structs inheriting from and implementing interfaces
On Tue, 02 Jan 2018 00:54:13 +, Laeeth Isharc wrote: > On Friday, 29 December 2017 at 12:59:21 UTC, rjframe wrote: >> On Fri, 29 Dec 2017 12:39:25 +, Nicholas Wilson wrote: >> >> I've actually thought about doing this to get rid of a bunch of if >> qualifiers in my function declarations. `static interface {}` compiles >> but doesn't [currently] seem to mean anything to the compiler, but >> could be a hint to the programmer that nothing will directly implement >> it; it's a compile-time interface. This would provide a more generic >> way of doing stuff like `isInputRange`, etc. > > Atila does something like this > > https://code.dlang.org/packages/concepts Thanks; I actually started skimming through his repositories a couple of days ago, but didn't see this. --Ryan
Re: structs inheriting from and implementing interfaces
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: In C#, structs can inherit from and implement interfaces. using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, Mike You want wrap: https://dlang.org/phobos/std_typecons.html#wrap
Re: structs inheriting from and implementing interfaces
On Friday, 29 December 2017 at 12:59:21 UTC, rjframe wrote: On Fri, 29 Dec 2017 12:39:25 +, Nicholas Wilson wrote: On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: The problem is that interfaces are a runtime thing (e.g. you can cast a class to an interface) structs implement compile time interfaces via template duck typing (usually enforced via an if()). you could probably write a wrapper that introspected an interface and enforced that all members were implemented. I've actually thought about doing this to get rid of a bunch of if qualifiers in my function declarations. `static interface {}` compiles but doesn't [currently] seem to mean anything to the compiler, but could be a hint to the programmer that nothing will directly implement it; it's a compile-time interface. This would provide a more generic way of doing stuff like `isInputRange`, etc. Atila does something like this https://code.dlang.org/packages/concepts
Re: static if and early exit from function doesn't seem to work?
On Sunday, 31 December 2017 at 13:47:32 UTC, Adam D. Ruppe wrote: On Sunday, 31 December 2017 at 13:32:03 UTC, aliak wrote: So it seems it tries to compile the statements below the check on V.length even though it's guaranteed to be true and there's a return statement inside the if. Yeah, static if includes or excludes code independently at compile time. So what you wrote there would be like, assuming the first to static ifs pass: auto concat(R, V...)(R range, V values) if (isInputRange!R) { import std.range: chain, ElementType; return range; return range.chain(values[0]).concat(values[1..$]); } The code is still there, even if it isn't reached due to an early return, and thus still must compile. Using else static if means it won't be generated. Ah ok, thanks! So it is intended behavior. I wonder if treating a return like a static else would be a good idea though. I at least can't see how it would break anything at this time.
Re: How do you safely deal with range.front?
On Monday, 1 January 2018 at 02:18:36 UTC, Jonathan M Davis wrote: Except that the reason for arrays throwing RangeErrors when you try and index them out-of-bounds is to avoid memory safety issues, which is not necessarily the case at all when you're talking about ranges. Having ranges in general be checking empty in front, popFront, back, etc. would add unnecessary overhead - especially when you consider that ranges often wrap other ranges. You'd be layering on check after check when the calling code is already supposed to be checking empty when necessary to make sure that the range isn't empty. You'd even be layering checks on top of the checks that arrays already do, since many ranges are ultimately wrapped around a dynamic array at their core. [...] Makes sense. Especially after pointing out that ranges are mostly arrays at the end. Thanks!
Re: How do you safely deal with range.front?
On Monday, 1 January 2018 at 04:18:29 UTC, Ali Çehreli wrote: If you're fine with specifying the function as a template argument, the following works. (As seen with 's => s.foo()' below, you have to use a lambda for member functions anyway.) Ali Nice! Thanks :) And I think your usage for something named "ifFront" actually makes more sense than using it to return "saferef" functionality. I've basically implemented an optional type for now and the "iffront" implementation looks like this: import std.range: isInputRange; auto iffront(Range)(Range r) if (isInputRange!Range) { import std.range: ElementType, empty, front; import optional: no, some; return r.empty ? no!(ElementType!Range) : some(r.front); } unittest { import std.algorithm: filter; assert([false].filter!"a".iffront.empty); // because optional is a range } unittest { import std.algorithm: filter; import optional: some, none; struct A { int f() { return 7; } } assert([A()].filter!"false".iffront.f == none); assert([A()].filter!"true".iffront.f == some(7)); } And thanks everyone for the input. I'll play around with some of the ideas and see what comes of it.
Re: std.file and non-English filename in Windows
I think you have to decode your input to UTF-8. stdin .byLineCopy(No.keepTerminator) .each!((string file_name_raw) { // change Latin1String to the code page of your console; // use the 'chcp' command to see the current code page of your console // import std.encoding; auto raw = cast(immutable( Latin1String)[]) file_name_raw; string file_name_utf8; transcode(raw, file_name_utf8); writefln("%s --> %s", file_name_utf8, file_name_utf8.exists); });
Does UDA not work for enums?
I got compilers errors from this: enum E { @("foo") A, @("baa") B } I got: Error: basic type expected, not @ Error: no identifier for declarator _error_ Error: type only allowed if anonymous enum and no enum type Error: if type, there must be an initializer Error: found @ when expecting , [...]
Re: Does UDA not work for enums?
On Monday, 1 January 2018 at 17:15:24 UTC, Marc wrote: I got compilers errors from this: enum E { @("foo") A, @("baa") B } I got: Error: basic type expected, not @ Error: no identifier for declarator _error_ Error: type only allowed if anonymous enum and no enum type Error: if type, there must be an initializer Error: found @ when expecting , [...] Vote for and help/improve this DIP: https://github.com/dlang/DIPs/pull/105
Re: std.file and non-English filename in Windows
On Monday, 1 January 2018 at 16:13:06 UTC, Domain wrote: On Monday, 1 January 2018 at 12:33:27 UTC, John Chapman wrote: On Sunday, 31 December 2017 at 18:21:29 UTC, Domain wrote: In Windows, exists, rename, copy will report file not exists when you input non-English filename, such as Chinese 中文.txt Works for me. I created a file with the name "中文.txt" and std.file.exists returned true. Is your D source file saved in ASCII by any chance? Try saving it with a different encoding, such as UTF8. Yes, "中文.txt".exists return true. But when then filename read from stdin, it return false stdin .byLineCopy(No.keepTerminator) .each!((a) { writefln("%s --> %s", a, a.exists); }); dir *.txt /b | test.exe English.txt --> true 中文.txt --> false Problem solved! I change the properties of cmd from "Raster Fonts" to "Consolas" and all work well. But I don't know why.
Re: Help optimizing code?
On Monday, 1 January 2018 at 16:47:40 UTC, Adam D. Ruppe wrote: On Monday, 1 January 2018 at 16:13:37 UTC, Muld wrote: If you use .ptr then you get zero detection, even in debug builds. It is limited to the one expression where you wrote it, instead of on the ENTIRE program like the build switches do. It is a lot easier to check correctness in an individual expression than it is to check the entire program, including stuff you didn't even realize might have been a problem. With the .ptr pattern, it is correct by default and you individually change ones you (should) look carefully at. With -boundscheck, it is wrong by default and most people don't even look at it - people suggest it to newbies as an optimization without mentioning how nasty it is. It won't be just one line though. When you pretty much have to use it EVERYWHERE to get the optimization you want. It makes more sense to just turn off the check for the entire program and use your own asserts() where they are actually needed. That way you still get the checks in debug builds and have asserts where they are actually necessary. I'd rather there be a potential bug than the program running to slow to be usable That's a ridiculous exaggeration. In this program, I saw a < 1% time difference using those flags. -O -inline make a 50x bigger difference! Read the sentence right before this.. Jesus. People only read what they want. or have zero debugging for indices in debug builds. You shouldn't be using .ptr until after you've carefully checked and debugged the line of code where you are writing it. That's the beauty of the pattern: it only affects one line of code, so you can test it before you use it without affecting the rest of the program. It won't just be one line, and that's not beautiful. What happens when code gets refactored? You are constantly going to be flip-flopping the source code rather than a compiler flag or using multiple build configurations? How long are you even going to test for? The error that might happen for the code is probably difficult to detect, if it wasn't then having bounds checking at all wouldn't be necessary. Just test your code, that's the beauty of testing!
Re: Help optimizing code?
On Monday, 1 January 2018 at 16:13:37 UTC, Muld wrote: If you use .ptr then you get zero detection, even in debug builds. It is limited to the one expression where you wrote it, instead of on the ENTIRE program like the build switches do. It is a lot easier to check correctness in an individual expression than it is to check the entire program, including stuff you didn't even realize might have been a problem. With the .ptr pattern, it is correct by default and you individually change ones you (should) look carefully at. With -boundscheck, it is wrong by default and most people don't even look at it - people suggest it to newbies as an optimization without mentioning how nasty it is. I'd rather there be a potential bug than the program running to slow to be usable That's a ridiculous exaggeration. In this program, I saw a < 1% time difference using those flags. -O -inline make a 50x bigger difference! or have zero debugging for indices in debug builds. You shouldn't be using .ptr until after you've carefully checked and debugged the line of code where you are writing it. That's the beauty of the pattern: it only affects one line of code, so you can test it before you use it without affecting the rest of the program.
Re: std.file and non-English filename in Windows
On Monday, 1 January 2018 at 12:33:27 UTC, John Chapman wrote: On Sunday, 31 December 2017 at 18:21:29 UTC, Domain wrote: In Windows, exists, rename, copy will report file not exists when you input non-English filename, such as Chinese 中文.txt Works for me. I created a file with the name "中文.txt" and std.file.exists returned true. Is your D source file saved in ASCII by any chance? Try saving it with a different encoding, such as UTF8. Yes, "中文.txt".exists return true. But when then filename read from stdin, it return false stdin .byLineCopy(No.keepTerminator) .each!((a) { writefln("%s --> %s", a, a.exists); }); dir *.txt /b | test.exe English.txt --> true 中文.txt --> false
Re: Help optimizing code?
On Monday, 1 January 2018 at 15:54:33 UTC, Adam D. Ruppe wrote: On Monday, 1 January 2018 at 15:29:28 UTC, user1234 wrote: dmd mandelbrot.d -O -release -inline -boundscheck=off -O and -inline are OK, but -release and -boundscheck are harmful and shouldn't be used. Yeah, you can squeeze a bit of speed out of them, but there's another way to do it - `.ptr` on the individual accesses or versioning out unwanted `assert` statements - and those avoid major bug and security baggage that -release and -boundscheck=off bring. If you use .ptr then you get zero detection, even in debug builds. In this program, I didn't see a major improvement with the boundscheck skipping... and in this program, it seems to be written without the bugs, but still, I am against that switch on principle. It is so so so easy to break things with them. In this program, it's relatively small and doesn't look like it does its calculations in realtime. I'd rather there be a potential bug than the program running to slow to be usable, or have zero debugging for indices in debug builds.
Re: Help optimizing code?
On Monday, 1 January 2018 at 15:29:28 UTC, user1234 wrote: dmd mandelbrot.d -O -release -inline -boundscheck=off -O and -inline are OK, but -release and -boundscheck are harmful and shouldn't be used. Yeah, you can squeeze a bit of speed out of them, but there's another way to do it - `.ptr` on the individual accesses or versioning out unwanted `assert` statements - and those avoid major bug and security baggage that -release and -boundscheck=off bring. In this program, I didn't see a major improvement with the boundscheck skipping... and in this program, it seems to be written without the bugs, but still, I am against that switch on principle. It is so so so easy to break things with them. - I'd use "double" instead of "real". On my computer at least, float gave 2x speed compared to double. You could try both though and see which works better.
Re: Help optimizing code?
On Monday, 1 January 2018 at 15:23:19 UTC, Adam D. Ruppe wrote: On Monday, 1 January 2018 at 15:09:53 UTC, Lily wrote: I started learning D a few days ago, coming from some very basic C++ knowledge, and I'd like some help getting a program to run faster. So a few easy things you can do: 1) use `float` instead of `real`. real sucks, it is really slow and weird. Making that one switch doubled the speed on my computer. Yes I've also adviced double. Double is better if the target arch is X86_64 since part of the operations will be made with SSE. With "real" the OP was **sure** to get 100% of the maths done in the FPU (although for all the trigo stuff there's no choice) 2) preallocate the imageData. before the loop, `imageData.reserve(width*height*3)`. Small savings on my computer but an easy one. 3) make sure you use the compiler optimization options like `-O` and `-inline` on dmd (or use the gdc and ldc compilers both of which generally optimize better than dmd out of the box). And if that isn't enough we can look into smaller things, but these overall brought the time down to about 1/3 what it started on my box.
Re: Help optimizing code?
On Monday, 1 January 2018 at 15:09:53 UTC, Lily wrote: I started learning D a few days ago, coming from some very basic C++ knowledge, and I'd like some help getting a program to run faster. The code is here: https://github.com/IndigoLily/D-mandelbrot/blob/master/mandelbrot.d Right now it runs slower than my JavaScript Mandelbrot renderer on the same quality settings, which is clearly ridiculous, but I don't know what to do to fix it. Sorry for the lack of comments, but I can never tell what will and won't be obvious to other people. - The first thing is to compile with the best options: dmd mandelbrot.d -O -release -inline -boundscheck=off - You append a lot, which can cause reallocs for imageData; Try import std.array; Appender!(ubyte[]) imageData; The code will not have to be changed for "~=" since Appender overloads this operator. - I'd use "double" instead of "real".
Re: Help optimizing code?
On Monday, 1 January 2018 at 15:09:53 UTC, Lily wrote: I started learning D a few days ago, coming from some very basic C++ knowledge, and I'd like some help getting a program to run faster. So a few easy things you can do: 1) use `float` instead of `real`. real sucks, it is really slow and weird. Making that one switch doubled the speed on my computer. 2) preallocate the imageData. before the loop, `imageData.reserve(width*height*3)`. Small savings on my computer but an easy one. 3) make sure you use the compiler optimization options like `-O` and `-inline` on dmd (or use the gdc and ldc compilers both of which generally optimize better than dmd out of the box). And if that isn't enough we can look into smaller things, but these overall brought the time down to about 1/3 what it started on my box.
Help optimizing code?
I started learning D a few days ago, coming from some very basic C++ knowledge, and I'd like some help getting a program to run faster. The code is here: https://github.com/IndigoLily/D-mandelbrot/blob/master/mandelbrot.d Right now it runs slower than my JavaScript Mandelbrot renderer on the same quality settings, which is clearly ridiculous, but I don't know what to do to fix it. Sorry for the lack of comments, but I can never tell what will and won't be obvious to other people.
Re: Finding unsafe line of code
On Friday, 29 December 2017 at 10:33:16 UTC, Johan Engelen wrote: On Friday, 29 December 2017 at 10:23:24 UTC, codephantom wrote: On Friday, 29 December 2017 at 09:38:50 UTC, Vino wrote: Let me re-frame the question with an example, as the Dsafe the below line of code is considered as unsafe(Pointer arithmetic), ... ini[10] a; int* p = [0]; for (size_t i=0; i <= 10; i++) p[i] = ...; From, Vino.B Is this what you're looking for? https://dlang.org/spec/function.html#safe-functions Just annotate your functions with @safe (as @system is the default). Or if that's not possible, you can add runtime checks with ASan: http://johanengelen.github.io/ldc/2017/12/25/LDC-and-AddressSanitizer.html -Johan Hi, Tried to install LDC on Windows 7, but getting the below errors while compiling Installed s/w .Net 4.7.1 .Net Core Runtime 2.0.4 .Net SDK 2.1.3 Windows SDK 10.0.16299.15 Environment Variables Set: NETFXSDKDir = C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\x86(System/User) LDC_VSDIR = C:\Program Files (x86)\Microsoft Visual Studio\2017\Community(System) Error: C:\Users\bheev1\Desktop\Current\Script\Complied-64>ldc2 -fsanitize=address -g nscleaner.d LINK : fatal error LNK1181: cannot open input file 'kernel32.lib' Error: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\bin\HostX64\x64\link.exe failed with status: 1181 From, Vino.B
Re: std.file and non-English filename in Windows
On Sunday, 31 December 2017 at 18:21:29 UTC, Domain wrote: In Windows, exists, rename, copy will report file not exists when you input non-English filename, such as Chinese 中文.txt Works for me. I created a file with the name "中文.txt" and std.file.exists returned true. Is your D source file saved in ASCII by any chance? Try saving it with a different encoding, such as UTF8.
Re: std.file and non-English filename in Windows
On Monday, January 01, 2018 10:47:51 Patrick Schluter via Digitalmars-d- learn wrote: > On Sunday, 31 December 2017 at 18:21:29 UTC, Domain wrote: > > In Windows, exists, rename, copy will report file not exists > > when you input non-English filename, such as Chinese 中文.txt > > It's unclear what your problem is but here a wild guess. > > Windows API's for Unicode use UTF-16 as far as I know. Strings in > D are utf-8. So before calling win32 API function, they have to > be transformed to wstring i.e. utf-16 strings. std.file abstracts all of that away for you, and it does have at least some tests that use Unicode characters, though I think that most of the functions don't have tests that use Unicode characters. I would not have expected a Unicode bug like this to be in std.file, but it's certainly possible. It's also possible that the console needs to be set to UTF-8 or UTF-16 or something, since the default often seems to cause problems for folks - though unless the file names are coming from the command-line, I wouldn't have expected that to be an issue. I do almost nothing with Windows though, so I'm not very familiar with the ins and outs of that mess. - Jonathan M Davis
Re: Slices and Dynamic Arrays
On Monday, 1 January 2018 at 02:10:14 UTC, Jonathan M Davis wrote: On Sunday, December 31, 2017 14:49:40 Tony via Digitalmars-d-learn wrote: On Sunday, 31 December 2017 at 14:24:40 UTC, Jonathan M Davis wrote: > [...] The DLang Tour also uses the term slice to refer to T[]. "The type of arr is int[], which is also called a slice." "A slice consists of two members - a pointer to the starting element and the length of the slice:" Presumably, because whoever wrote that preferred the terminology used in the D Slices article. Regardless, it's not wrong to call them slices. It's just less precise, since the term slice refers to more than dynamic arrays. The DLang Tour should probably be fixed to use the term dynamic array though. - Jonathan M Davis Editing a page is just one click away - there is an edit button on the top. Any improvements are always welcome!
Re: std.file and non-English filename in Windows
On Sunday, 31 December 2017 at 18:21:29 UTC, Domain wrote: In Windows, exists, rename, copy will report file not exists when you input non-English filename, such as Chinese 中文.txt It's unclear what your problem is but here a wild guess. Windows API's for Unicode use UTF-16 as far as I know. Strings in D are utf-8. So before calling win32 API function, they have to be transformed to wstring i.e. utf-16 strings.