Discussions related to Visual Prolog
choibakk
Active Member
Posts: 35
Joined: 5 Sep 2019 19:30

Memory Questions

Unread post by choibakk »

I've finished NADYA2.0 chess, and since the PDC profiler is broken, I'm trying to improve performance by rewriting components I deem to be slower. I was testing trying to achieve the fastest direct memory access I can achieve and was playing will the following snippet.

But I want to verify I have a proper understanding of a couple of questions before preceding.

My two immediate questions are:

1. Are "class" facts (not object facts) global across all threads or thread local (I'm planning on making the next iteration of the chess engine multi-threaded).

2. If I allocate memory using "memory::allocAtomicHeap", my understanding from the documentation is that the garbage collector will not scan that memory for cleanup. However, the pointer itself, will eventually be cleanup up after it goes out of scope. Is this true?

Thanks in advance,
Craig Hoibakk

Code: Select all

implement memtest     open core   class facts     ptr:pointer := erroneous.     itemSize:positive := 10.   clauses     new() :-         %  I don't want this checked by the garbage collector to check this memory (for performance), but want it cleaned up then the         %  object goes out of scope...         ptr := memory::allocAtomicHeap(sizeOfDomain(integer64) * itemSize, memory::contextType_binary),         init_data(),         fast_data_access().   predicates     init_data:(). clauses     init_data() :-         %  simulating random access to set items         I = std::downTo(9, 0),         T1_ = uncheckedConvert(integerNative, ptr),         T2_ = T1_ + sizeofDomain(integer64) * I,         IndexPtr = uncheckedConvert(pointer, T2_),         memory::setInteger64(IndexPtr, I),         fail         ;         succeed.   %  I can call this on my laptop 10 million times in just over 3 seconds clauses     fast_data_access() :-         %  simulating random access to get items         I = std::downTo(9, 0),         T1_ = uncheckedConvert(integerNative, ptr),         T2_ = T1_ + sizeofDomain(integer64) * I,         IndexPtr = uncheckedConvert(pointer, T2_),         I64 = memory::getInteger64(IndexPtr),           fail         ;         succeed.     end implement memtest  
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Re: Memory Questions

Unread post by Thomas Linder Puls »

  • Yes, class facts are shared between all threads.
  • Yes, memory allocated by memory::allocAtomicHeap is not scanned for pointers but is itself subject to garbage collection.
If an object is shared between threads the the corresponding object facts are also shared between the threads (through the object, of course).

The way you use the class fact is strange/suspicious: When you create an object you will allocate a new buffer and replace the one that was there before, that seems wrong.

I am not sure why you want many objects that provides an interface to the same buffer at all. But given that this is what you want. I think your code should look like this:

Code: Select all

interface memtest   predicates     fast_data_access : ().   end interface memtest   class memtest : memtest end class memtest   implement memtest     open core   constants     itemCount : positive = 10.     itemSize : byteCount = sizeOfDomain(integer64).   class facts     ptr : pointer.   class predicates     init_data : () [classInitializer]. clauses     init_data() :-         ptr := memory::allocAtomicHeap(itemSize * itemCount),         foreach I = std::cIterate(itemCount) do             T1 = uncheckedConvert(unsignedNative, ptr),             T2 = T1 + itemSize * I,             IndexPtr = uncheckedConvert(pointer, T2),             memory::setInteger64(IndexPtr, I)         end foreach.   clauses     fast_data_access() :-         foreach I = std::downTo(itemCount - 1, 0) do             T1 = uncheckedConvert(unsignedNative, ptr),             T2 = T1 + itemSize * I,             IndexPtr = uncheckedConvert(pointer, T2),             _I64 = memory::getInteger64(IndexPtr)         end foreach.   end implement memtest
The key point is that the ptr fact is only initialized once, which is achieved by using a classInitializer predicate. (I have also "beautified" your code in other ways, as you can see).

As mentioned you don't really need the object(s) at all: fast_data_access can equally well be a class predicate:

Code: Select all

class memtest   predicates     fast_data_access : ().   end class memtest
Regards Thomas Linder Puls
PDC
choibakk
Active Member
Posts: 35
Joined: 5 Sep 2019 19:30

Re: Memory Questions

Unread post by choibakk »

Thanks Thomas,

The "class facts" was only written that way in the sample, to emphasize the first question. I wrote a vector class that shares some of the code but has no "class" facts. This sample was only used for testing this kind of "direct" memory access for performance.

Thank your for the clear explanation.

Cheers,
Craig Hoibakk
Post Reply