• Advertisement
Sign in to follow this  

Unity MSVC std::vector and aligned data

This topic is 2270 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I switched to the DirectXMath library when I switched to D3D11, and I'm running into this issue of Microsoft's std::vector implementation being incompatible with aligned data types. Looking around the 'Net it looks like the standard fixes are to avoid using std::vector, use a custom allocator, patch [s]vector::rebind[/s] vector::resize to take a const reference, or a combination of the latter two measures. But all the relevant pages I found were from 2008 or older.

So, what does the GD.net community suggest? And does anyone have a custom aligned allocator, or do I need to learn to write my own?

Share this post


Link to post
Share on other sites
Advertisement
Well, one solution would be not to use MSVC at all. If you are doing cross platform projects, you might as well be using MinGW on Windows, since you are likely using GCC already on other operating systems.

If you are not targeting Non-Microsoft OSes at all, you can still use MinGW.

If you must use MSVC, then you can replace the horrible Microsoft STL implementation with STLport.

Share this post


Link to post
Share on other sites

I switched to the DirectXMath library when I switched to D3D11, and I'm running into this issue of Microsoft's std::vector implementation being incompatible with aligned data types. Looking around the 'Net it looks like the standard fixes are to avoid using std::vector, use a custom allocator, patch vector::rebind to take a const reference, or a combination of the latter two measures. But all the relevant pages I found were from 2008 or older.

So, what does the GD.net community suggest? And does anyone have a custom aligned allocator, or do I need to learn to write my own?

If you have a specific additional memory allocation requirement (like a specific alignment) and you want to use a standard library container, you have to replace the default allocator with one that satisfies the additional requirement. This is not specific to any one C++ runtime. It is why allocators are a customization point in the standard library.

It is not difficult to write something that satisfies the allocator requirements, but you might want to have a good reference handy (like Josuttis) just in case.

Share this post


Link to post
Share on other sites

[If you have a specific additional memory allocation requirement (like a specific alignment) and you want to use a standard library container, you have to replace the default allocator with one that satisfies the additional requirement. This is not specific to any one C++ runtime. It is why allocators are a customization point in the standard library.

It is not difficult to write something that satisfies the allocator requirements, but you might want to have a good reference handy (like Josuttis) just in case.


No, the problem OP is having isn't related to memory allocators, it's related to the fact that Microsoft's STL uses the wrong parameter types in functions like vector::resize, effectively making their STL completely incompatible with aligned types, regardless of what allocator is used.

Share this post


Link to post
Share on other sites

If you must use MSVC, then you can replace the horrible Microsoft STL implementation with STLport.

MSVC has a fairly decent standard library implementation (the days of the lawsuits that prevented Microsoft from bundling a conformant library with MSVC6 after the previous C++ standard was released have been over for quite some time).

STLport does not come close to conforming to the current C++ standard.

Share this post


Link to post
Share on other sites
One solution is to use a std::vector replacement. For example, the bullet physics source code contains a class called [font="Courier New"]btAlignedObjectArray[/font], which is designed to solve your problem.
No, the problem OP is having isn't related to memory allocators, it's related to the fact that Microsoft's STL uses the wrong parameter types in functions like vector::resize, effectively making their STL completely incompatible with aligned types, regardless of what allocator is used.
No, the problem OP is having is related to standard allocators not satisfying non-default allocation requirements -- this is the same problem no matter what compiler/STL implementation you're using.
For example, on GCC, if you use the non-standard [font="Courier New"]__attribute__[/font] syntax to specify a non-default alignment value, then [font="Courier New"]std::vector[/font] won't work out of the box any more, due to the fact that this kind of structure alignment is non-standard.

Secondly, your information about Microsoft's 'STL' being non-standards compliant is incorrect, as of about 5 years ago.

Share this post


Link to post
Share on other sites
No, the problem OP is having is related to standard allocators not satisfying non-default allocation requirements -- this is the same problem no matter what compiler/STL implementation you're using.


MSVC (9 and 10, at least) both pass resize's _Val parameter by value, not const reference. Consequently, even if you write a custom allocator, you get a compiler error warning that the parameter cannot be aligned. So, whilst the allocator is needed, it seems disingenuous to say that the library implementation is entirely faultless.

Share this post


Link to post
Share on other sites

MSVC has a fairly decent standard library implementation (the days of the lawsuits that prevented Microsoft from bundling a conformant library with MSVC6 after the previous C++ standard was released have been over for quite some time).

STLport does not come close to conforming to the current C++ standard.


I was recommended STLport by multiple users here at GD.net just a year ago when I hade the exact same issue when using MSVC's srd::vector with 16 byte aligned float structures. I had an appropriate allocator made up, but because MSVC's STL passes by value in vector::resize, it is impossible to get anything buy compiler errors out of it.

This problem doesn't exist with STLport or GNU STL, so I stand by my statements.

Share this post


Link to post
Share on other sites
MSVC (9 and 10, at least) both pass resize's _Val parameter by value, not const reference.
Does the standard specify the signature as: [font="Courier New"]void resize(size_type sz, T c = T()) [/font]?
On my current project, the 3 different compilers that we use all comply with the above signature.

Share this post


Link to post
Share on other sites

[quote name='Bregma' timestamp='1317695717' post='4868808']
MSVC has a fairly decent standard library implementation (the days of the lawsuits that prevented Microsoft from bundling a conformant library with MSVC6 after the previous C++ standard was released have been over for quite some time).

STLport does not come close to conforming to the current C++ standard.


I was recommended STLport by multiple users here at GD.net just a year ago when I hade the exact same issue when using MSVC's srd::vector with 16 byte aligned float structures. I had an appropriate allocator made up, but because MSVC's STL passes by value in vector::resize, it is impossible to get anything buy compiler errors out of it.

This problem doesn't exist with STLport or GNU STL, so I stand by my statements.
[/quote]

Standing by observation is a good thing but understanding the problem is probably more important in this case. Basically the problem has nothing to do with the STL of VC but in a fundamental issue of C++ and how to interpret a semi-vague standard in this area. The STL definition of an allocator has nothing to do with memory alignment, worse, by definition the amount of allocation is requested by using "sizeof". So, a fully compliant STL only allows you to specify the initial address of a vector by overloading the allocator, it will (by standard) use sizeof to figure out how much memory to allocate for each element and as such the delta between elements in that memory. The STL versions you mention support "hacks" which work with padded structures instead of the basic "sizeof", it makes sense because that is "usually" what you want, but it is actually "against" standards compliance.

C++ doesn't support "alignment" directly, that's all done via extensions using pragma's, attributes etc. All such concepts are compiler specific and while rather stupid, VC's STL implementation doesn't take into account for these items. Stupid versus non compliant are very different things in this case. VC's STL since 2k8 versions have been exceptionally compliant.

The difference here is critical. VC's STL is actually the more compliant in this case, unfortunately it is not the most usable for what you want to do with it. Which version is better? One is very compliant and the others are cheating to be more usable. Given all the complexities in C++, I prefer more compliance so there are fewer invisible things going on behind my back.

Share this post


Link to post
Share on other sites

[quote name='TheUnbeliever' timestamp='1317696821' post='4868817']MSVC (9 and 10, at least) both pass resize's _Val parameter by value, not const reference.
Doesn't the standard specify the signature as: [font="Courier New"]void resize(size_type sz, T c = T()) [/font]?
On my current project, the 3 different compilers that we use all comply with the above signature.
[/quote]

I don't have access to a copy of the standard, so I can't honestly say. It's entirely plausible. In that case, maybe the word 'fault' isn't right to use, certainly not of the library. My point was really just that the combination of library and compiler mean that writing a custom allocator is insufficient to solve the problem - you must also patch vector to take a const reference. This was definitely the case with MSVC9. The library in 10 has stuck with the same signature, but perhaps the compiler allows alignment of function parameters. I can't remember if I've tried.

So, yeah - perhaps my wording is a little strong, but there's at least one additional problem which we don't have enough information (define 'incompatible', and which development environment are we using) to rule out. :o)

Share this post


Link to post
Share on other sites

Standing by observation is a good thing but understanding the problem is probably more important in this case. Basically the problem has nothing to do with the STL of VC but in a fundamental issue of C++ and how to interpret a semi-vague standard in this area. The STL definition of an allocator has nothing to do with memory alignment, worse, by definition the amount of allocation is requested by using "sizeof". So, a fully compliant STL only allows you to specify the initial address of a vector by overloading the allocator, it will (by standard) use sizeof to figure out how much memory to allocate for each element and as such the delta between elements in that memory. The STL versions you mention support "hacks" which work with padded structures instead of the basic "sizeof", it makes sense because that is "usually" what you want, but it is actually "against" standards compliance.

C++ doesn't support "alignment" directly, that's all done via extensions using pragma's, attributes etc. All such concepts are compiler specific and while rather stupid, VC's STL implementation doesn't take into account for these items. Stupid versus non compliant are very different things in this case. VC's STL since 2k8 versions have been exceptionally compliant.

The difference here is critical. VC's STL is actually the more compliant in this case, unfortunately it is not the most usable for what you want to do with it. Which version is better? One is very compliant and the others are cheating to be more usable. Given all the complexities in C++, I prefer more compliance so there are fewer invisible things going on behind my back.


Thanks for the clarification. Standards aside, OP as well as many of us find ourselves needing dynamic arrays of aligned data, so this is an issue which needs a solution.

Share this post


Link to post
Share on other sites

So, yeah - perhaps my wording is a little strong, but there's at least one additional problem which we don't have enough information (define 'incompatible', and which development environment are we using) to rule out. :o)

"Incompatible" means I'm getting this error:
error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
I apologize for not posting it earlier.

And I'm using MSVC 2010 Express on a Win7 64-bit machine (but compiling for 32-bit debug).

I guess I'm going to look into alternative containers and custom allocators and see which I prefer.

Share this post


Link to post
Share on other sites
"Incompatible" means I'm getting this error:
error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
I apologize for not posting it earlier.


Writing a custom allocator won't fix this: you either need to, standard be damned, patch the line in the header (the error presumably points to it) or use a replacement container. Either way, you will need a custom allocator as well.

Share this post


Link to post
Share on other sites

I don't have access to a copy of the standard, so I can't honestly say. It's entirely plausible.

For the record, ISO-14882 says this.
[23.3.6.2](11) [font="Courier New"]void resize(size_type sz, const T& c);[/font]

If the Microsoft implementation does not meet this requirement, it is nonconforming (ie. broken). Very unfortunate. The OP's problem will still obtain with other implementations because he needs to provide a custom allocator.

Also, for the record, STLport does not implement about 50% of the current standard library.

Share this post


Link to post
Share on other sites

[quote name='TheUnbeliever' timestamp='1317701806' post='4868848']
So, yeah - perhaps my wording is a little strong, but there's at least one additional problem which we don't have enough information (define 'incompatible', and which development environment are we using) to rule out. :o)

"Incompatible" means I'm getting this error:
error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
I apologize for not posting it earlier.

And I'm using MSVC 2010 Express on a Win7 64-bit machine (but compiling for 32-bit debug).

I guess I'm going to look into alternative containers and custom allocators and see which I prefer.
[/quote]

The above error you received is a problem with the Visual studio compiler cannot guarantee 16 byte alignment for variables that are copied on the stack. A fix to your problem is to compile your application as a 64 bit compile and you will not receive any errors. I would suggest going for 64 bit compiles as that is going to be the dominant os version.

You can read this http://thetweaker.wordpress.com/2010/05/05/stdvector-of-aligned-elements/

Share this post


Link to post
Share on other sites

If the Microsoft implementation does not meet this requirement, it is nonconforming (ie. broken). Very unfortunate.

After doing some more informed Googling, it appears that this is a relatively recent change to the standard, and that Microsoft actually complied here while many other vendors chose not to for the sake of usability. I can post a link later today that goes into more detail.

Edit: Here's the blog entry and followup I was talking about. I'm not sure when the revision occurred, but it looks like Microsoft's implementation of std::vector::resize() was compliant until the standard was revised.

Share this post


Link to post
Share on other sites

A fix to your problem is to compile your application as a 64 bit compile and you will not receive any errors.

I was under the impression that one could not compile for 64-bit applications with the Express edition of MSVC.

Share this post


Link to post
Share on other sites

Thanks for the clarification. Standards aside, OP as well as many of us find ourselves needing dynamic arrays of aligned data, so this is an issue which needs a solution.


I completely agree that we need a solution, sorry if I sounded like I was defending some gallant adherence to standards, that's not the case at all. I actually use a custom vector container because of these problems. If STL had been written with a policy based front end (i.e. not just the allocator but also internal behavior), it would have greatly helped correct the deficiencies and allow stl containers to adapt better to ongoing changes and requirements in programming. Unfortunately they were not and now they are starting to show deficiencies. (Personally, I thought they had a LOT of deficiencies for optimization reasons and hence wrote my own in many places as drop in replacements when it makes sense.)

Look at the basic problems with std::vector as examples:

1. Pod items are detected automatically and in cases where something "looks" non-pod but could be treated as pod, you can't do anything to change the STL behavior of copy construct/delete, which in "many" cases is stupid overhead. Deal with it or use a non-stl container.
2. No way to define stable/non-stable erasure. 90% of the time I don't care about stable erasures in a vector and as such some STL variations supply "fast_erase" or related functions which just move the last element to the erased elements location instead of shifting everything down by one. Of course, unless you target a single platform, you can't always use this and that causes big performance differences between platforms/libraries.
3. POD detection is so flakey given the lack of decent metadata in C++ that a huge portion of the time STL guesses wrong and by definition "most" of your std::vector's are doing stupid work behind your back.

This is a huge problem with C++ that needs to be corrected to make stl something even performance critical applications can/should use. Adding the concept of "alignment" requirements to C++ is also extremely important.

Share this post


Link to post
Share on other sites
FWIW, I decided to use btAlignedObjectArray; learning to write a custom allocator is a task for another day. I'm still fairly new to the use of aligned memory and whatever eases the curve is a short-term win.

Share this post


Link to post
Share on other sites
After reading this thread back in October, I had submitted a bug report to Microsoft about vector resize not taking a const reference. Some research had shown that it had been previously requested to be changed to a const reference, but it had been rejected to be fixed.

As you can see by the first link, this wll be fixed in VC11.


Hi,

Thanks for reporting this bug. We've fixed it, and the fix will be available in VC11.

Amusingly, when this was originally reported in July 2006 (months before I joined the VC team), this was indeed By Design. C++03 23.2.4.2 [lib.vector.capacity]/6 specified:

void resize(size_type sz, T c = T());

Now, C++11 23.3.6.3 [vector.capacity]/9, 11 specifies:

void resize(size_type sz);
void resize(size_type sz, const T& c);

This change was introduced in March 2008's Working Paper N2588.

If you have any further questions, feel free to E-mail me at stl@microsoft.com .

Stephan T. Lavavej
Visual C++ Libraries Developer
[/quote]

Share this post


Link to post
Share on other sites

As you can see by the first link, this wll be fixed in VC11.


I just had a quick check - this is in the version of <vector> in the vc11 developer preview.


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By 3dmodelerguy
      So I am building a turn based rogue-like (think CDDA). The game is going to have a very large map (up to 1000's x 1000's) however to alleviate most of that I obviously can't render everything so there will just be render a certain radius around the player and just load in and out data as the player moves.
      The next major system I am prototyping is making interactive tiles destructible and pretty much everything will be destructible besides basic landscape (cars, doors, windows, structures, etc. will be destructible)
      While I am only rendering a certain amount of tiles around the player, I want to keep the amount of colliders active at one time to be as small as possible for performance and currently the tilemap tool I use automatically merges colliders together.
      So instead of creating a separate colliders for each of these tiles and having the destructible behavior tied to that object (which my tilemap tool would allow me to do) I was thinking that I would store an array of all the X and Y locations for the interactive tilemap layer and let the tilemap manage the colliders. 
      Then when I hit a collider on the interactive tilemap layer, instead of of getting the behavior for how to deal with the destruction for that tile from that game object, I would pull it from the array I mentioned earlier based on the tile I attempt to interact with which I already have.
      Does this sound like a good approach? Any other recommendations would be welcomed.
    • By NDraskovic
      Hey guys,
      I have a really weird problem. I'm trying to get some data from a REST service. I'm using the following code:
       
      private void GetTheScores() { UnityWebRequest GetCommand = UnityWebRequest.Get(url); UnityWebRequestAsyncOperation operation = GetCommand.SendWebRequest(); if (!operation.webRequest.isNetworkError) { ResultsContainer rez = JsonUtility.FromJson<ResultsContainer>(operation.webRequest.downloadHandler.text); Debug.Log("Text: " + operation.webRequest.downloadHandler.text); } } The problem is that when I'm in Unity's editor, the request doesn't return anything (operation.webRequest.downloadHandler.text is empty, the Debug.Log command just prints "Text: "), but when I enter the debug mode and insert a breakpoint on that line, then it returns the text properly. Does anyone have an idea why is this happening?
      The real problem I'm trying to solve is that when I receive the text, I can't get the data from the JSON. The markup is really simple:
      [{"id":1,"name":"Player1"},{"id":2,"name":"Player2"}] and I have an object that should accept that data:
      [System.Serializable] public class ResultScript { public int id; public string name; } There is also a class that should accept the array of these objects (which the JSON is returning):
      [System.Serializable] public class ResultsContainer { public ResultScript[] results; } But when I run the code (in the debug mode, to get any result) I get an error: ArgumentException: JSON must represent an object type. I've googled it but none of the proposed solutions work for me.
      Also (regardless if I'm in the debug mode or not) when I try to do some string operations like removing or adding characters to the GET result, the functions return an empty string as a result
      Can you help me with any of these problems?
      Thank you
    • By nihitori
      The Emotional Music Vol. I pack focuses on beautiful and esoteric orchestral music, capable of creating truly emotive and intimate moods. It features detailed chamber strings, cello and piano as the main instruments, resulting in a subtle and elegant sound never before heard in video game royalty-free music assets.

      The pack includes 5 original tracks, as well as a total of 47 loops based on these tracks (long loops for simple use and short loops for custom / complex music layering).

      Unity Asset Store link: https://www.assetstore.unity3d.com/en/#!/content/107032
      Unreal Engine Marketplace link: https://www.unrealengine.com/marketplace/emotional-music-vol-i

      A 15 seconds preview of each main track is available on Soundcloud:
       
    • By RoKabium Games
      Another one of our new UI for #screenshotsaturday. This is the inventory screen for showing what animal fossils you have collected so far. #gamedev #indiedev #sama
    • By eldwin11929
      We're looking for programmers for our project.
      Our project is being made in Unity
      Requirements:
      -Skills in Unity
      -C#
      -Javascript
      -Node.js
      We're looking for programmers who can perform a variety of functions on our project.
      Project is a top-down hack-and-slash pvp dungeon-crawler like game. Game is entirely multiplayer based, using randomized dungeons, and a unique combat system with emphasis on gameplay.
      We have a GDD to work off of, and a Lead Programmer you would work under.
      Assignments may include:
      -Creating new scripts of varying degrees specific to the project (mostly server-side, but sometimes client-side)
      -Assembling already created monsters/characters with existing or non-existing code.
      -Creating VFX
      -Assembling already created environment models
      If interested, please contact: eldwin11929@yahoo.com
      This project is unpaid, but with royalties.
       
      ---
      Additional Project Info:
      Summary:
      Bassetune Reapers is a Player-verus-Player, competitive dungeon crawler. This basically takes on aspects of dungeon crawling, but with a more aggressive setting. Players will have the option to play as the "dungeon-crawlers" (called the 'Knights', or "Knight Class", in-game) or as the "dungeon" itself (literally called the 'Bosses', or "Boss Class", in-game). What this means is that players can choose to play as the people invading the dungeon, or as the dungeon-holders themselves.
      Key Features:
      -Intense, fast-paced combat
      -Multiple skills, weapons, and ways to play the game
      -Tons of different Bosses, Minibosses, creatures and traps to utilize throughout the dungeon
      -Multiple unique environments
      -Interesting, detailed lore behind both the game and world
      -Intricate RPG system
      -Ladder and ranking system
      -Lots of customization for both classes s of customization for both classes
  • Advertisement