From: jeffreycameron on 11 Feb 2006 16:58 Hello all, I'm trying to implement AWE in my application. So far I have done this : 1. Enabled the Lock Pages in Memory privilege for my account 2. Used the AWE example code function to enable and disable this privilege for my app. 3. Set up a memory allocation wrapper function that makes calls to: a. Determine the number of pages I need b. Set up a PFN array c. Call AllocateUserPhysicalPages and pass in the PFN array d. Call VirtualAlloc (I also tried VirtualAllocEx) to reserve the memory e. Call MapUserPhysicalPages to map the memory. I'm not concerned about deallocating the stuff just yet, that will come later. Right now I believe the memory is freed when the process dies anyway so it isn't a big concern for me. The server I am running this on has 32GB of RAM and is running Windows Advanced Server 2003. The /PAE switch is in the boot.ini file and enabled. During usual running the server is using about 310MB of RAM for the processes and such that are on it already. Much less than the 32GB available. My problem is when I try to allocate large memory chunks. I can allocate up to 500MB with AWE no problem, then I have a single huge allocation of close to 800MB after this. When I try to make this single huge allocation the program fails!! I was under the impression that with PAE X86 and AWE my 32-bit pointers could/would point to physical memory up to 64GB in range ... so why the hell is it not working?? I do mix regular heap allocation (using calloc) with the AWE stuff. I try to localise the usage of AWE to the really large arrays of data I need. Could this be a cause? Can someone please help and tell me what the devil is going on? Thanks in advance! p.s. YES I really do need this much memory!! Working with caches and memory-mapped files would be too slow for the application I want to use.
From: jeffreycameron on 12 Feb 2006 14:46 Sorry, I should have added earlier, that when I said the allocation failed it failed on a call to VirtualAlloc with GetLastError reporting there wasn't enough memory to handle the request.
From: Carl Daniel [VC++ MVP] on 12 Feb 2006 15:20 jeffreycameron(a)gmail.com wrote: > Sorry, I should have added earlier, that when I said the allocation > failed it failed on a call to VirtualAlloc with GetLastError reporting > there wasn't enough memory to handle the request. Are you actually allocating any AWE memory? Unless you're calling AllocateUserPhysicalPages and MapUserPhysicalPages, you're not using AWE memory. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/address_windowing_extensions.asp for details. -cd
From: Jeffrey on 12 Feb 2006 17:14 Hi Carl, Yes, i'm calling AllocateUserPhysicalPages (which is successful) and then calling VirtualAlloc (which fails). After VirtualAlloc I would then call MapUserPhysicalPages. So my cycles goes (see code below): First invocation: 1. Call AllocateUserPhysicalPages (#pages for 500MB RAM) [Success] 2. Call VirtualAlloc (500MB RAM) [Success] 3. Call MapUserPhysicalPages (#pages for 500MB RAM) [Success] Second invocation: 1. Call AllocateUserPhysicalPages (#pages for 800MB RAM) [Success] 2. Call VirtualAlloc (800MB of RAM) [Failure] 3. GetLastError reports not enough memory to fulfill request. Sorry for little specifics, but i'm at home typing this. There is no internet access at my workstation for security reasons. So the first time I call my function it succeeds, the second time it fails. The total of memory between them is app. 1.3GB. My server has 32GB of RAM and PAE enabled. 4GT is turned off. [CODE SNIPPET] AWERegionDescriptor *region; SYSTEM_INFO info; ULONG_PTR pages_requested; BOOL rAWEesult; PVOID ptr; int ret_code; int page_size = 0; /* determine the page size of this computer */ GetSystemInfo(&info); page_size = info.dwPageSize; pages_requested = ((nb_elem * elem_size) / page_size) + 1; /* allocate the space for the region descriptor */ region = (AWERegionDescriptor*) ccalloc(1, sizeof(AWERegionDescriptor)); region->nb_pages = pages_requested; region->pfn_array = (ULONG_PTR*) HeapAlloc(GetProcessHeap(), 0, region->nb_pages * sizeof(ULONG_PTR)); /* reserve the physical pages in memory */ result = AllocateUserPhysicalPages(GetCurrentProcess(), &(region->nb_pages), region->pfn_array); if (result == FALSE) { /* print error */ } if (pages_requested != region->nb_pages) { /* print error */ } /* allocate the pointer */ ptr = VirtualAlloc(NULL, nb_elem * elem_size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE); /* ensure memory was available */ if (ptr == NULL) { /* print an error */ } else { /* map the physical memory into the AWE region */ result = MapUserPhysicalPages(ptr, region->nb_pages, region->pfn_array); if (result == FALSE) { /* print error */ } } return ptr; [END CODE SNIPPET] Carl Daniel [VC++ MVP] wrote: > jeffreycameron(a)gmail.com wrote: > >>Sorry, I should have added earlier, that when I said the allocation >>failed it failed on a call to VirtualAlloc with GetLastError reporting >>there wasn't enough memory to handle the request. > > > Are you actually allocating any AWE memory? Unless you're calling > AllocateUserPhysicalPages and MapUserPhysicalPages, you're not using AWE > memory. > > See > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/address_windowing_extensions.asp > for details. > > -cd > >
From: Ivan Brugiolo [MSFT] on 12 Feb 2006 19:11
Form the description of the problem, it seems that the address space of the process does not have a large enought contiguous address range to map the view of the physical memory. Virtual address space of a process is still limited to 2/3/4 Gig, depending if the application is running on a regular, /3G and LargeAddressAware, Wow64 and LargeAddressAware. Virtual address space is being used by heap segments, threads's stacks, module mapping, user mapping, etc, etc. I would recoment running the `!address -summary` command in any recent cdb/ntsd/windbg debugger, and see what is the largest contigious range of addressed onto which you can create a map (and, at the same time, you would see what else the address space is being used for). To give you the idea, in a regular process with just "int main(int,char **){}", you can expect to have 1.9Gig of contiguous address range, that would allou you to map about 1/17th of the 32Gig of physical memory you have at any given time. More complex process would allow you less. -- -- This posting is provided "AS IS" with no warranties, and confers no rights. Use of any included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm "Jeffrey" <jeffreycameron(a)gmail.com> wrote in message news:ejNl3GCMGHA.4064(a)TK2MSFTNGP10.phx.gbl... > Hi Carl, > > Yes, i'm calling AllocateUserPhysicalPages (which is successful) and then > calling VirtualAlloc (which fails). After VirtualAlloc I would then call > MapUserPhysicalPages. So my cycles goes (see code below): > > First invocation: > 1. Call AllocateUserPhysicalPages (#pages for 500MB RAM) [Success] > 2. Call VirtualAlloc (500MB RAM) [Success] > 3. Call MapUserPhysicalPages (#pages for 500MB RAM) [Success] > > Second invocation: > 1. Call AllocateUserPhysicalPages (#pages for 800MB RAM) [Success] > 2. Call VirtualAlloc (800MB of RAM) [Failure] > 3. GetLastError reports not enough memory to fulfill request. > > Sorry for little specifics, but i'm at home typing this. There is no > internet access at my workstation for security reasons. > > So the first time I call my function it succeeds, the second time it > fails. The total of memory between them is app. 1.3GB. My server has 32GB > of RAM and PAE enabled. 4GT is turned off. > > [CODE SNIPPET] > > AWERegionDescriptor *region; > SYSTEM_INFO info; > ULONG_PTR pages_requested; > BOOL rAWEesult; > PVOID ptr; > int ret_code; > int page_size = 0; > > /* determine the page size of this computer */ > > GetSystemInfo(&info); > page_size = info.dwPageSize; > pages_requested = ((nb_elem * elem_size) / page_size) + 1; > > /* allocate the space for the region descriptor */ > > region = (AWERegionDescriptor*) ccalloc(1, > sizeof(AWERegionDescriptor)); > region->nb_pages = pages_requested; > region->pfn_array = (ULONG_PTR*) HeapAlloc(GetProcessHeap(), 0, > region->nb_pages * sizeof(ULONG_PTR)); > > /* reserve the physical pages in memory */ > > result = AllocateUserPhysicalPages(GetCurrentProcess(), > &(region->nb_pages), region->pfn_array); > > if (result == FALSE) > { > /* print error */ > } > > if (pages_requested != region->nb_pages) > { > /* print error */ > } > > /* allocate the pointer */ > > ptr = VirtualAlloc(NULL, nb_elem * elem_size, MEM_RESERVE | > MEM_PHYSICAL, PAGE_READWRITE); > > /* ensure memory was available */ > > if (ptr == NULL) > { > /* print an error */ > } > else > { > /* map the physical memory into the AWE region */ > > result = MapUserPhysicalPages(ptr, region->nb_pages, > region->pfn_array); > > if (result == FALSE) > { > /* print error */ > } > } > > return ptr; > > [END CODE SNIPPET] > > Carl Daniel [VC++ MVP] wrote: >> jeffreycameron(a)gmail.com wrote: >> >>>Sorry, I should have added earlier, that when I said the allocation >>>failed it failed on a call to VirtualAlloc with GetLastError reporting >>>there wasn't enough memory to handle the request. >> >> >> Are you actually allocating any AWE memory? Unless you're calling >> AllocateUserPhysicalPages and MapUserPhysicalPages, you're not using AWE >> memory. >> >> See >> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/address_windowing_extensions.asp >> for details. >> >> -cd >> |