Page Errors and .Net Programming

I am reading a book on operating systems, and it provides some C examples that I basically understand. The example I'm looking at now shows two almost identical pieces of code that will work on a dummy system ...

int i, j; int [128] [128] data; for (j = 0; j < 128; j++) for (i = 0; i < 128; i++) data [i] [j] = 0; 

And the second part of the code

 int i, j; int [128] [128] data; for (i = 0; i < 128; i++) for (j = 0; j < 128; j++) data [i] [j] = 0; 

On this particular system, the first section of code will lead to errors on page 16k, and the second will only result in 128.

My apologies if this is a stupid question, but in my experience with .NET, I have always been pretty much memoryless. I just create a variable, and it is "somewhere", but I do not know where I do not care.

My question is: how to compare .NET with these C examples in this fictional system (pages have 128 words in size, each array line occupies one full page. In the first example, we set one int on page 1, then one int on page 2 and so .d., while the second example sets all int on page 1, then all int on page 2, etc.)

Also, although I think I understand why the code creates different levels of swap, is there anything meaningful that I can do with it? Does the page size depend on the operating system? Does this call, as a general rule, to access memory in an array as bolder as possible?

+4
source share
3 answers

Fake operating systems can be useful for demonstrating principles, but no real operating system that I know about really works that way. You can only get 16K pages if the page is immediately disabled after use. Although it is technically possible for this, the machine must be under heavy load, desperate from RAM to support a set of running processes. At this point, you no longer care about performance, the machine will still slow down the scan. The technical term for this is thrashing .

There is something much more important in this code that you haven't talked about. A level 1 CPU cache plays an important role in quickly accessing array elements. A cache line (usually 64 bytes) is populated from memory on first access. Access to the next item at the following memory address is very cheap, the data is already in the cache. Accessing an array with the first index change is very expensive, it requires another cache line fill, which can take hundreds of cycles, in the worst case. Having a significant risk of crowding out an existing cache line that also contains array data, level 1 cache is not very large. Obtaining this right requires knowledge of how the elements of the runtime array are stored in memory.

+7
source

Your two samples are identical, but presumably what you want:

 int i, j; int [128] [128] data; for (i = 0; i < 128; i++) for (j = 0; j < 128; j++) data [i] [j] = 0; // <--- i,j 

And the second part of the code

 int i, j; int [128] [128] data; for (i = 0; i < 128; i++) for (j = 0; j < 128; j++) data [j] [i] = 0; // <--- j,i 

Thus, assuming a page size of 128 * sizeof (int):

  • in one case, you are repeating the array sequentially. In this case, the worst number of page errors is the size of the array in pages = 1.

  • in another case, you go to a new page at each iteration, so in the worst case, you may have a page error at each iteration of the loop.

The situation is exactly the same in .NET.

+2
source

The number of page errors you get will depend on the number of pages that you access that are not in memory.

Pages on the stack are likely to be in memory, if this is not the first time that the stack has been used to this extent.

Assuming your page size is 4 KB, like on many systems, and none of the pages are in memory, you will be accessing 128 * 128 * 4 bytes or 64 KB, which is 16 pages. Note: this structure can be on 17 pages, if it does not start at the page border, in which case the first page will be in memory.

As long as you access each page, it does not matter how you access them or in what order.


Perhaps you are talking about cache misses, and the order of access to the data can make a difference. In this case, it is best to access the data gradually at the latest index. those. for a[i][j] you want the inner loop to use j However, if your cache is large enough, this may make a difference. This can be very different for really large structures that do not fit into faster caches.

0
source

All Articles