Is an array of arrays cache local? - memory

If an array
[1,2,3,4,5,6]
exists in a contiguous block of memory, does an array of arrays
[[1,2,3],[4,5,6]]
necessarily have the same cache locality?

In the array of arrays case, the arrays themselves will have the same locality properties that an array of elements has because this case is no different - the "elements" here are arrays. However, whether or not the elements of each sub-array are contiguous in memory to the elements of another sub-array depends on the implementation of the sub-arrays.
Since you didn't specify a language, I'll use C++ syntax to demonstrate, but this is fundamentally language agnostic, as it deals with aspects of the hardware. If your array-of-arrays is equivalent to the C++ std::vector<std::vector<int>> - which is a flexible container of containers that can grow/shrink as needed, each std::vector will be contiguous in memory with respect to the others, but a std::vector doesn't contain the elements directly. Rather, its a wrapper around a dynamically allocated array, typically holding a few pointers to the underlying data. What this means is that each wrapper will be contiguous, but the elements won't necessarily be. Here's a live demo demonstrating this.
However, consider the case where your array-of-arrays is a std::array<std::array<int,3>,2> instead - which is simply an array of 2 elements, where each element is an array of the fixed size ,3, ints. A std::array is a wrapper around a fixed-size C array which is not dynamically allocated, in contrast to its std::vector counterpart. In this case, you get the same locality property as you did for the std::vector case - each std::array is contiguous with respet to the others, but here you also get something more. Since a std::array actually contains the underlying data rather than just a few pointers to it, the elements of each sub-array are also contiguous with respect to each other. This, too can be seen here.
What this boils down to from a hardware perspective is simply how your objects are laid down in memory. In the former case, each wrapper is contiguous, but the data isn't, because the wrappers simply hold pointers to the data. In the latter case, each wrapper is contiguous, and so is the data, because each wrapper actually contains the data.
Perhaps if you specify which language you're referring to, I could help you with your specific case.

Related

Are there considerable drawbacks to use Swift's ContiguousArray? If so, which are there?

Apple's ContiguousArray Documentation describes it as:
The ContiguousArray type is a specialized array that always stores its elements in a contiguous region of memory. This contrasts with Array, which can store its elements in either a contiguous region of memory or an NSArray instance if its Element type is a class or #objc protocol.
If your array’s Element type is a class or #objc protocol and you do not need to bridge the array to NSArray or pass the array to Objective-C APIs, using ContiguousArray may be more efficient and have more predictable performance than Array. If the array’s Element type is a struct or enumeration, Array and ContiguousArray should have similar efficiency.
To me this sounds like a ContiguousArray is always preferable to a regular Array since it has at least the same performance. Yet in my (perhaps too limited) experience with swift so far I've never seen anybody use a ContiguousArray instead of an Array and the description seems almost too good to be true.
I could not find any lists of drawbacks of ContiguousArrays online. I could imagine that while it is running faster, it has a less favourable memory usage than an array, but I can't find any information backing this. Can somebody with more understanding of the matter please help me to understand if there's a trade-off to expect when using ContiguousArrays?

Nested fixed-size arrays/records

I want to model fixed-size arrays that can contain records and other fixed-size arrays. I then want to model store and select accesses to them.
I currently use ArraySorts for the arrays and Datatypes for the records. However, according to this answer (arrays) and this answer (records), these aren't really intended for my usecase. Is there anything else in Z3 I could use instead?
Background: I want to model pointers as they occur in the LLVM IR. For this, each pointer has a data array that represents the memory buffer into which it is pointing and an indices array that represents the indices used in getelementptr calls. Since the memory buffer could contain pointers or structs, I need to be able to nest the arrays (or store the records in arrays).
An example (in z3py) looks like this:
Vec3 = z3.Datatype("Vec3")
Vec3.declare("Vec3__init",
("x", z3.IntSort()),
("y", z3.IntSort()),
("z", z3.IntSort())
)
Vec3 = Vec3.create()
PointerVec3 = z3.Datatype("Pointer__Vec3")
PointerVec3.declare("Pointer__Vec3__init",
("data", z3.ArraySort(z3.BitVecSort(32), Vec3)),
("nindices", z3.IntSort()),
("indices", z3.ArraySort(z3.IntSort(), z3.BitVecSort(32)))
)
PointerVec3 = PointerVec3.create()
Arrays and records are the only way to model these things in z3/SMT-Lib. And they can be nested as you wish.
It is true that SMTLib arrays are not quite like arrays you find in regular programming languages. But it's not true that they are always unbounded. Their size exactly matches the cardinality of their domain. If you want a bounded array, I recommend using an appropriate BitVec type for your source. For an n-bit bit vector, your array will have 2^n elements. You can work with a small enough n, and treat that as your array; which typically matches what you see in practice: Most of such internal arrays will be a power-of-two anyhow. (Moreover, provers usually don't do well with large arrays; so sticking to a small power-of-two is a good idea, at least to start with.)
So, these are your only options. Stack-overflow works the best if you try it out and actually ask about what sort of problems you ran into.

Why implement an immutable list as a linked-list?

According to F#'s list documentation:
"A list in F# is an ordered, immutable series of elements of the same type"
"Lists in F# are implemented as singly linked lists"
Why not implement it contiguously in memory since it immutable and thus has a fixed size? Why ever use an F# list instead of an F# array?
They serve different purposes, for instance:
You use an Array in F# to store big amounts of data that needs to be accessed randomly with relative low overhead.
A List in F# is useful when you need to accumulate something over iterations of a recursive function. Arrays don't play well here, since they have a fixed size.
With a list, you can prepend all elements of ListM (size M) to ListN (size N) in O(M) time. Similarly, you can prepend a single Element to any list in O(1) time.

Optimal storage for string/integer pairs with fast lookup of strings?

I need to maintain correspondence between strings and integers, then lookup the string value and return the integer. What's the best structure to store this info that meets the following requirements:
Speed and memory size are important, in that order.
I don't want to reinvent the wheel and write my own sorting routine. A call to Sort(CompareFunction) is fine of course.
Conditions:
The integers are not guaranteed to be sequential, neither is there a 'start value' like 0 or 1
Number of data pairs can vary from 100 to 100000
The data are all read in at the beginning, there's no subsequent additions/deletions/modifications
FWIW the strings are the hex entry ID's that Outlook (MAPI?) uses to identify entries. Example: 00000000FE42AA0A18C71A10E8850B651C24000003000000040000000000000018000000000000001E7FDF4152B0E944BA66DFBF2C6A6416E4F52000487F22
There's so many options (TStringList (with objects or name/value pairs), TObjectList, TDictionary, ...) that I'd better ask for advice first...
I have read How can I search faster for name/value pairs in a Delphi TStringList? which suggest TDictionary for string/string pairs, and Sorting multidimensional array in Delphi 2007 which suggest TStringlist objects for string/integer but where sorting is done on the integers.
The second link that you include in the question is not applicable. That is a question concerning sorting rather than efficient lookup. Although you discuss sorting a number of times in your question, you do not have a requirement to sort. Your requirement is simply a dictionary, also known as an associative array. Of course, you can implement that by sorting an array and using binary search for your lookup, but sorting is not a requirement. You simply need an efficient dictionary.
Out of the box, the most efficient and convenient data structure for your problem is TDictionary<string, Integer>. This has lookup complexity of O(1) and so scales well for large collections. For smaller collections a binary search based lookup with lookup complexity of O(log n) can be competitive and can indeed out-perform a dictionary.
Cosmin Prund wrote an excellent answer here on SO where he compared the performance of dictionary lookup against binary search based lookup. I recommend you have a read. I would say that for small containers, performance is probably not that big a problem for you. So even though binary search may be quicker, it probably does not matter because your performance is good either way. But performance probably becomes an issue for larger containers and that's where the dictionary is always stronger. For large enough containers, the performance of binary search may become unacceptable.
I'm sure that it is possible to produce more efficient implementations of dictionaries than the Embarcadero one, but I'd also say that the Embarcadero implementation is perfectly solid. It uses a decent hash function and does not have any glaring weaknesses.
In terms of memory complexity, there's little to choose between a dictionary and a sorted array. It's not possible to improve on a sorted array for memory use.
I suggest that you start with TDictionary<string, Integer> and only look beyond that if your performance requirements are not met.
It seems you are going to lookup long evenly distributed strings. One of the fastest data structures for this kind of problem is Trie.
But your dataset size is rather small, and ready-to-use Delphi solutions like THashedStringList or TDictionary (more convenient) would provide a fairly high speed.

id values of different variables in python 3

I am able to understand immutability with python (surprisingly simple too). Let's say I assign a number to
x = 42
print(id(x))
print(id(42))
On both counts, the value I get is
505494448
My question is, does python interpreter allot ids to all the numbers, alphabets, True/False in the memory before the environment loads? If it doesn't, how are the ids kept track of? Or am I looking at this in the wrong way? Can someone explain it please?
What you're seeing is an implementation detail (an internal optimization) calling interning. This is a technique (used by implementations of a number of languages including Java and Lua) which aliases names or variables to be references to single object instances where that's possible or feasible.
You should not depend on this behavior. It's not part of the language's formal specification and there are no guarantees that separate literal references to a string or integer will be interned nor that a given set of operations (string or numeric) yielding a given object will be interned against otherwise identical objects.
I've heard that the C Python implementation does include a set of the first hundred or so integers as statically instantiated immutable objects. I suspect that other very high level language run-time libraries are likely to include similar optimizations: the first hundred integers are used very frequently by most non-trivial fragments of code.
In terms of how such things are implemented ... for strings and larger integers it would make sense for Python to maintain these as dictionaries. Thus any expression yielding an integer (and perhaps even floats) and strings (at least sufficiently short strings) would be hashed, looked up in the appropriate (internal) object dictionary, added if necessary and then returned as references to the resulting object.
You can do your own similar interning of any sorts of custom object you like by wrapping the instantiation in your own calls to your own class static dictionary.

Resources