|
netcat posted:Here's something I thought was kinda strange. The following does not compile: This is a bug with GCC, though all is not as it appears. If we change the std::vector<foo> to a std::array<foo, 2>, it will compile (We add the extra braces for aggregate initialization that std::array requires of course). However, removing the = sign shows a different set of compiler errors: code:
code:
This is definitely a bug, just not the bug it seems to be. I've run into this with a recursive variadic unrestricted union-like variant class I was writing for a while. Huge PITA, and it basically destroys the point of having a variant in the first place. Bit of a show stopper.
|
# ? May 28, 2013 23:01 |
|
|
# ? May 26, 2024 20:49 |
|
Is there any benefit to declaring a couple of these variables outside of this loop? For example, if I declared 'glyph' before the loop, and then set it to Mat::zeros... within the loop, would that keep using the same bit of memory vs using a new bit of memory each time through the loop? code:
|
# ? May 28, 2013 23:25 |
|
If Mat is backed by a heap allocation, then yes, it is likely to perform better if you re-initialize the same allocation every iteration instead of allocating and freeing it each time. You might also consider not spuriously copying the vectors of points in g and reusing the same vector (or even a fixed-size array) for glyphCorners.
|
# ? May 28, 2013 23:34 |
|
rjmccall posted:If Mat is backed by a heap allocation, then yes, it is likely to perform better if you re-initialize the same allocation every iteration instead of allocating and freeing it each time. Actually, I don't think that code will even work, since glyphCorners wouldn't be cleared out at the start of the next loop, right? I need to have only 4 corners for the perspective matrix function to work.
|
# ? May 28, 2013 23:40 |
|
bobua posted:Actually, I don't think that code will even work, since glyphCorners wouldn't be cleared out at the start of the next loop, right? I need to have only 4 corners for the perspective matrix function to work. Just do a glyphCorners.clear(). In all practical implementations that doesn't actually deallocate any memory, so repeating that plus the four .push_backs per iteration is cheap.
|
# ? May 28, 2013 23:44 |
|
Updated to this.code:
|
# ? May 28, 2013 23:47 |
|
bobua posted:Updated to this. Most likely your Mat class doesn't do any heap allocations, in which case moving them outside of the loop likely doesn't make a difference (should be quick to check). More importantly though, you never want to return the pointer to a stack variable from a function; as soon as the function exits, the stack frame becomes invalid and any stack allocated objects get destructed. Either return the std::vector by value (probably ok due to return-value optimization), or pass a reference to an output vector as an argument. Vinterstum fucked around with this message at 23:57 on May 28, 2013 |
# ? May 28, 2013 23:54 |
|
Vinterstum posted:Most likely your Mat class doesn't do any heap allocations, in which case moving them outside of the loop likely doesn't make a difference (should be quick to check). How would I check if something does heap allocations just out of curiosity? Not sure if I understand that last part... Are you saying add something like std::vector<Mat>* myVariable to 'fixGlyphs' argument list, then setting myVariable = &glyphImages instead of using return?
|
# ? May 29, 2013 00:08 |
|
I think Mat is heap-backed; among other things, it doesn't seem to have fixed dimensions.bobua posted:
I'm guessing that Mat::zeros returns a Mat, right? So this still does a heap-allocation and then copies from that into glyph. If you're going to try to optimize allocations, you really want an in-place version of this.
|
# ? May 29, 2013 00:11 |
|
bobua posted:How would I check if something does heap allocations just out of curiosity? You'd have to check the actual code of the Mat class. I wouldn't worry too much about it though; your current implementation is fine. bobua posted:Not sure if I understand that last part... Are you saying add something like std::vector<Mat>* myVariable to 'fixGlyphs' argument list, then setting myVariable = &glyphImages instead of using return? No that would still just return a pointer to an object which isn't valid anymore. Consider a bit more of a minimal example: code:
The alternatives are: * Instead of allocating "numbers" on the stack, we could allocate it on the heap. I.e. code:
* Simpler would just be to return the vector by value rather than returning a pointer to it. In theory this can incur some copying of the vector which would be efficient, but in practice the compiler should optimize this away. code:
Vinterstum fucked around with this message at 00:30 on May 29, 2013 |
# ? May 29, 2013 00:25 |
|
bobua posted:How would I check if something does heap allocations just out of curiosity? The easiest way is to think about the type's API. A type's direct storage is always constant-sized, so if Mat can store arbitrary sizes of things, then it has to be heap-backed at some point. Another way is to look at the fields in the type to see how it stores the elements. If it contains an array (or a std::array), it might not be heap-backed. If it just has a pointer or a std::vector or something like that, it's heap-backed. A third way is to just look at the implementations of things like the copy-constructor and check for uses of malloc or new. quote:Not sure if I understand that last part... Are you saying add something like std::vector<Mat>* myVariable to 'fixGlyphs' argument list, then setting myVariable = &glyphImages instead of using return? No. Make the function return a std::vector<Mat> directly (not a pointer to one), or add a std::vector<Mat>& argument and just push things onto that directly.
|
# ? May 29, 2013 00:26 |
|
rjmccall posted:I think Mat is heap-backed; among other things, it doesn't seem to have fixed dimensions. Yeah looks like you're right; this appears to be part of the OpenCV library and in this case used as actual bitmap data for a glyph..? I'm too used to Matrix == Matrix4x4, I guess.
|
# ? May 29, 2013 00:35 |
|
Okay, I did this before you guys posted, and I'm not getting why it wouldn't work...code:
code:
|
# ? May 29, 2013 00:39 |
|
bobua posted:Okay, I did this before you guys posted, and I'm not getting why it wouldn't work... No, in this case you'd be overwriting whatever memory the uninitialized MyMat pointer is pointing to (and likely crash). You need to have an actual object to assign to: code:
Vinterstum fucked around with this message at 00:46 on May 29, 2013 |
# ? May 29, 2013 00:44 |
|
Vinterstum posted:No, in this case you'd be overwriting whatever memory the uninitialized MyMat pointer is pointing to (and likely crash). You need to have an actual object to assign to: I tried that, but when I tried to do MyMat.push_back or *MyMat.push_back intellisense says 'expression must have class type'
|
# ? May 29, 2013 00:49 |
|
karoshi posted:Correct. Optimization priority list: Alright, thanks! The acceleration structure of course comes first, the whole talk about cache basically started from trying to explain the performance difference between two processors. I was thinking of using an octree as I'm familiar with quadtrees, but what could be better here, a kd-tree perhaps?
|
# ? May 29, 2013 00:52 |
|
bobua posted:I tried that, but when I tried to do MyMat.push_back or *MyMat.push_back intellisense says 'expression must have class type' Assuming MyMat is is the name of the parameter to FixGlyphs and it's a pointer type, try MyMat->push_back(glyph) or (*MyMat).push_back(). I think at this point I'd really recommend picking up a C++ textbook though, and focus on pointers/references and stack vs. heap. No offense, but it feels like you're trying to do something a bit over your current C++ level.
|
# ? May 29, 2013 00:55 |
|
Vinterstum posted:Assuming MyMat is is the name of the parameter to FixGlyphs and it's a pointer type, try MyMat->push_back(glyph) or (*MyMat).push_back(). drat it, I didn't bother with the error because I just assumed it didn't work like that, first link on google is a recommendation to use -> which I 'knew about' from the book I'm reading but hadn't run into needing it yet. No offense taken, I am way over my head. It's just for fun though, and working on a random program that isn't interesting to me would just make me move on to something else. Appreciate the help.
|
# ? May 29, 2013 01:00 |
|
There's entirely too many colons in this thread. As a C programmer that makes me sad.
|
# ? May 29, 2013 01:02 |
|
ratbert90 posted:There's entirely too many colons in this thread. As a C programmer that makes me sad. I feel the same way buddy
|
# ? May 29, 2013 01:06 |
|
mobby_6kl posted:Alright, thanks! The acceleration structure of course comes first, the whole talk about cache basically started from trying to explain the performance difference between two processors. I was thinking of using an octree as I'm familiar with quadtrees, but what could be better here, a kd-tree perhaps? This maybe should move into the graphics thread at this point. Anyhow, by all means, start with an octree. They're the easiest structure to implement and going from checking a million triangles to checking a hundred with an octree is more of an improvement than potentially going from checking a hundred to checking ten by using something more optimal. What you ideally you want is to use a structure that has cells of variable size in order to use heuristics (specifically, the surface area heuristic) to select better splitting points than always splitting in the middle like an octree. Octrees tend to fit badly to where the geometrical complexity of a scene is: for instance, imagine that you're rendering a mostly empty room save for a small geometrically complicated statue on a table somewhere in it. The octree will cheerfully divide the entire region of space near the statue into finer and finer chunks and any ray that even passes within the same quadrant (err. octant?) has to traverse a decent depth, but the ideal behavior is to construct the structure so that almost the first thing tested is if a ray comes close to the statue (within the bounding box, say). Discarding the complicated regions early in a trace like that can lower the average traversal depth by a lot. kd-trees work well for this and are fairly simple to implement and a simple AABB hierarchy (which a kd-tree is basically a special and more compressible case of) is also pretty reasonable. For reading, Ingo Wald's phd thesis has a chapter on kd-tree construction and traversal which is pretty detailed, it's what I used first time I implemented this stuff. Googling for a bit got me to some slides on acceleration structures which cover the relevant bits with pretty pictures as well as why the surface area heuristic is good for you. The slides make BVHs sound a lot more limited than they actually are though, for some reason.
|
# ? May 29, 2013 09:46 |
|
astr0man posted:I feel the same way buddy Why can't people just use enums and call it good? Just ignore the vast libraries that make life easy for you in C++!
|
# ? May 29, 2013 16:42 |
|
ratbert90 posted:Why can't people just use enums and call it good? Just ignore the vast libraries that make life easy for you in C++! Use enums for everything! code:
|
# ? May 29, 2013 16:45 |
|
Xerophyte posted:Not that cache isn't important, but you implement an acceleration structure so that you can render a scene with a million triangles by doing collision tests with 4 triangles and 25 planes per trace. Less thrashing the cache is a nice side effect but in optimization its a far distant second to just improving the algorithmic efficiency of the intersection search. This is also why the most significant potential improvement after implementing an octree is implementing something faster than an octree -- octrees build fast but traverse (comparably, it's still an exponential improvement over nothing) slow. I agree. I assume everybody knows that algorithmic optimization (from O(n**3) to O(n**2), or whatever) is the best optimization. It's when trying to optimize further, once the algorithm stands, that people tend to forget about cache. Or at least I did . Sometimes sorting your data costs 1.5% run-time and gives you a 70% boost. I was surprised when I read some VFX's guy comments about the new raytracing PCIe boards https://www.caustic.com/series2/index.html Imagination is launching. The top one has 16GB, apparently VFX people love huge scenes, too.
|
# ? May 29, 2013 17:03 |
|
SAHChandler posted:Use enums for everything! I was thinking: code:
|
# ? May 29, 2013 17:09 |
|
Staring at my code and I can't help but feel like I'm doing something stupid. For anybody not familiar with the SQLite API (most everybody?), a pointer to struct sqlite3 (db) is closed by the function sqlite3_close(), mind blowing stuff. It returns an error code; SQLITE_OK means it closed properly, anything else and something is preventing it's closure, like a prepared statement that hasn't been finalized.C++ code:
ratbert90 posted:Why can't people just use enums and call it good? Just ignore the vast libraries that make life easy for you in C++! I was using enums so that I could communicate SQL data types between classes, but I switched it over to #define constant bits so that I can whip up masks for combining data types if they're unsupported by the library.
|
# ? May 30, 2013 00:36 |
|
That's why Google added sqlite3_close_v2() .
|
# ? May 30, 2013 00:59 |
|
I was using enums, then I needed to associate a string with an enum value for human readable file I/O...code:
|
# ? May 30, 2013 01:21 |
|
MrMoo posted:That's why Google added sqlite3_close_v2() . I coulda sworn that the v2 functions require you to use v2 throughout or something, which provides functionality I mostly do not need. To be fair, this is only one of those things that I'm fretting over to keep it safe and not an issue I've run into yet.
|
# ? May 30, 2013 01:41 |
|
Ephphatha posted:I was using enums, then I needed to associate a string with an enum value for human readable file I/O... Just have to_string and from_string functions for the enum and/or overload stream extraction and insertion operators -- no need for a separate type to encapsulate it. Also, old-style exception specifications are deprecated, use noexcept specifications instead.
|
# ? May 30, 2013 01:52 |
|
I was wondering about good practices when trying to assert for memory leaks in tests, particularly when those tests are using 3rd-party code. The stuff I have tried generally compares two snapshots of the heap before and after something runs, and I usually use a closure to encapsulate the test so anything that is on the stack gets a chance to leave scope. Something like this:code:
|
# ? May 30, 2013 06:05 |
|
You're probably going to get a bunch of false positives from stuff that's lazy-initialized but is essentially supposed to persist for the life of the process. One thing you could try is to run the test once, take a snapshot, and then run the test again and take another snapshot - anything new in between those two snapshots is more likely to be an actual leak than just lazy initialization or whatever.
|
# ? May 30, 2013 07:13 |
|
That Turkey Story posted:Just have to_string and from_string functions for the enum and/or overload stream extraction and insertion operators -- no need for a separate type to encapsulate it. Also, old-style exception specifications are deprecated, use noexcept specifications instead. Thanks for the advice, however I found out that Qt provides a QMetaEnum object that can be used to get details about an enum. So my serialisation code ended up looking like: code:
code:
|
# ? May 30, 2013 15:39 |
|
I'm having more problems similar to ones I had before. Making a new class "student", with private data my_name, my_qualityPoints, and my_credits. Most of the errors I'm getting are while MSVC is compiling student.cpp. The first is "iostream(10): error C2143: syntax error : missing ';' before 'namespace'". I get four "syntax : identifier 'my_credits'" errors when referencing my_credits in the following function header (but not in other locations):code:
Any help with any of these?
|
# ? Jun 1, 2013 01:57 |
|
if statements should have parentheses around their conditions, but that's not necessarily your only problem.
|
# ? Jun 1, 2013 02:58 |
|
hooah posted:I'm having more problems similar to ones I had before. Making a new class "student", with private data my_name, my_qualityPoints, and my_credits. Most of the errors I'm getting are while MSVC is compiling student.cpp. The first is "iostream(10): error C2143: syntax error : missing ';' before 'namespace'". I get four "syntax : identifier 'my_credits'" errors when referencing my_credits in the following function header (but not in other locations): i think, in the class in the header you've not finished it with a semi-colon (after the closing brace)
|
# ? Jun 1, 2013 03:47 |
|
Also, hooah posted:Edit: Turns out I had the wrong grid.cpp file File locating is apparently going to be the bane of my existence with coding. Umm, how do and why would you have multiple copies of the same file floating around? this is something that you should correct.
|
# ? Jun 1, 2013 03:54 |
|
BirdOfPlay posted:Also, Before I knew what I was doing with file arrangement (if I even do now), I moved copied the original from its folder to that folder's parent, which is my project folder. Then I changed one of those files. As for the other stuff, I appreciate the quick replies, but I'll have to wait until I can sit down with this again. In the meantime, I have 14 hours of travelling to look forward to!
|
# ? Jun 1, 2013 04:49 |
|
Jabor posted:You're probably going to get a bunch of false positives from stuff that's lazy-initialized but is essentially supposed to persist for the life of the process.
|
# ? Jun 2, 2013 06:32 |
|
|
# ? May 26, 2024 20:49 |
|
Rocko Bonaparte posted:I assume you mean I could diff a snapshot between a run I thought was okay versus a later one for the sake of nailing down regressions. I can't imagine if I was running the test for the first time that I'd necessarily nail any leaks that already happened. I'm just trying to understand the implications of what you wrote. I guess it confirms what I suspected; one can normally expect little bits and pieces like that. What I was suggesting is that you run the test once to completion, take a heap snapshot, and then (on the same heap) run all your tests again and take a second snapshot afterwards. The idea is that the first test run forces all the lazy initialization to happen, so comparing the two snapshots allows to see everything that's leaking more memory every time it's run.
|
# ? Jun 2, 2013 08:13 |