Shop Learn
KonneX thoughts, comments and questions - Page 2 — Parallax Forums

KonneX thoughts, comments and questions

2»

Comments

  • NixNix Posts: 18

    @VBBSim said:
    Earlier I did a Early Adopter presentation a bit like yours using TLC ( Touch Logic Control ) which is a parallel visual language in Virtual Breadboard. TLC is a bit like visual ladder logic and it works as a non-programmer language where you click on visual elements in VBB and program by 'doing'. This creates executable storyboards. Here is the presentation.
    -----------------SNIP----------------------

    I can see what you're doing. I've used Simulator / IDE packages before.... Not as nice as yours though.

    However, there is one massive difference between our systems. Each of your macros(?) is it's own independent thread. You as the programmer must control these threads assigning activities to each. You pointed out that the number of threads is limited by number of cogs.
    My system is completely independent of number of cogs/cores and the programmer does not even have to think about the number of threads or what they're doing. Code created in KonneX would run on a single core ARM or an AMD Ryzen 3000, 128 core CPU, utilising as many cores as was necessary.

  • My system is completely independent of number of cogs/cores and the programmer does not even have to think about the number of threads or what they're doing. Code created in KonneX would run on a single core ARM or an AMD Ryzen 3000, 128 core CPU, utilising as many cores as was necessary.

    Can you elaborate on how you achieve that? The examples I’ve seen in the video are “classic” graphical programming that I’m familiar with from e.g. Max/MSP. It’s s different paradigm, foregoing the stack for message passing.

    But I don’t see how this lends itself to any improvements on concurrency. How do you solve the problems of synchronization, atomic updates, buffering?

  • NixNix Posts: 18

    @deets said:

    My system is completely independent of number of cogs/cores and the programmer does not even have to think about the number of threads or what they're doing. Code created in KonneX would run on a single core ARM or an AMD Ryzen 3000, 128 core CPU, utilising as many cores as was necessary.

    Can you elaborate on how you achieve that? The examples I’ve seen in the video are “classic” graphical programming that I’m familiar with from e.g. Max/MSP. It’s s different paradigm, foregoing the stack for message passing.

    But I don’t see how this lends itself to any improvements on concurrency. How do you solve the problems of synchronization, atomic updates, buffering?

    It took four years development and struggle, so you can probably appreciate that it's not going to be simple to explain how it works in a single reply, but I'll have a go.

    KonneX works on the principle of virtual processors. Simple processors with only 5 registers (Resource register, data register, program counter, stack pointer and ID)
    Now, the term "virtual processor" does not mean that it emulates a CPU (like Java, for example). It is simply a term that adequately describes what goes on.
    The virtual processor has a very limited range of instructions, limited to thread synchronisation and object locking. I doesn't even have basic integer mathematics.
    When it encounters an instruction it doesn't understand, it instigates a search. Like the 68000 or 80486 CPUs when they encounter a floating point instruction.
    When the required instruction has been located, the instruction (which is simply a call to the correct library function) can be executed independently on its own real CPU core.

    So, let us look at an example.

    In the image above, there is an instruction marked with "*". This is an integer multiply instruction from an included library.
    There are two values that are required for this operation. The top one is the integer signal value given to the "Set Turret Position" instruction (a value between 0 and 5), by it's calling code.
    The bottom input comes from the black box. The black box is a built in VP instruction that simply generates a constant integer signal when triggered. The value here is the servo range (180 degrees) divided by the number of possible turret positions (5) = 36.

    Let us follow the paths of execution, leading to this multiply.
    Each instruction starts with a single VP (with the calling data).
    The required turret position value is separated from the input data (the cyan/black dot.... I will have to improve this), creating a new VP.
    It is then copied to three separate threads. (You will notice that one of these threads is black, we will come to that later). Creating 2 new VPs.
    The top thread goes to be stored in a temporary buffer near exit 1, and the VP for this thread is destroyed.
    The lower (blue) one goes into the multiply instruction. However, the other value required (the constant value) hasn't been provided yet, so the turret position value is stored in the instruction's buffer and the VP is destroyed.
    The lower (black) line is used to trigger the creation of the constant value. The reason it is black is because it's actual value is unimportant. Black simply indicates that it is used a s NULL trigger.
    The VP on this thread, picks up the constant value (36) and puts it into its resource register.
    It then moves on to the multiply instruction, providing the required second value for the operation.
    Because all the inputs for the multiply have now been satisfied, the VP proceeds to locate the integer library function and then executes it.
    The resulting value (turret position * 36) is then put into the data buffer for the Servo.Write instruction.

    Meanwhile (and completely independently) the initial VP has copied the data path and created a new VP in the process (the top cyan/black lines).
    The very top of these two goes to another buffer (near Exit 0) dumps its data and dies.
    The lower of the two cyan/black lines goes to an instruction called "Pickup". This is another built in VP instruction that loads the object handle for the turret servo from the robot's data. This handle is loaded into the resource register of the VP running that thread.
    The VP then moves on to the Servo.Write instruction and dumps the servo handle into the instruction buffer.

    It doesn't matter which VP gets to the "Write" instruction first or second. The first one dumps its resource register data into the buffer and dies.
    The second, picks up all of the buffered data, locates the "Write" instruction within the "Servo" library and executes the function.

    Now, "Servo" is an object, and as such, the "Write" instruction requires a handle. It is at this point where object locking can occur.
    Prior to executing "Write", the kernel checks the object locks and determines if it is safe to execute the "Write" instruction.
    If it is not safe (because it is being accessed elsewhere), the thread is moved to a queue, where it waits for the object to become free.

    Side note. In this particular example, locking won't actually be necessary and so won't be implemented in the manner described. I only use it as an example.

    Continuing our journey, the "Write" instruction has two exits. The top one is the primary one, where the operation was successful. (The output data is just the servo object handle, but it turns black for reasons we''ll see in a moment).
    The lower exit for the "Write" instruction is an error. This is the path taken if the position provided was invalid.
    Only one path from any instruction is chosen. It is not possible for an instruction to have two or more "live" exits.
    So, in our example, it the turret position given was in range, the top exit is chosen, the VP picks up the value stored in the buffer (small triangle) placed there earlier, and then goes on to exit 0 (OK).
    Exit 0 of our map is defined in its instruction definition as outputting the robot's object handle, so the buffer is just there to store this value until it is needed.
    Exit 1, on the other hand, is defined to output the errant position value and so, likewise the provided position value is buffered, just in case.

    The actual definition of the instructions created by the programmer is entirely up to him (or her). What values are output is a totally free choice. Error exits, could simply be NULL signals if the programmer so desired. However, when defining new instructions, it is good to always ask the question: What would be useful? As such with the "Servo.Write" instruction, it might be useful to be able to examine the errant position value, either in the crash report (if the Exit 1 of your instruction is not implemented in any calling code), or by more code that might be able to do something useful with the data.
    For example in an integer overflow situation the instruction to add two 16 bit integers can overflow (an error)... however, that error and the value in that register are useful when extending that add function to perform a 32 bit sum.

  • I can't help but wonder how hard it would be to use KonneX to generate OpenCL compute shader code. This feels like it would very well target high performance streaming processors like modern gpus.

  • NixNix Posts: 18

    @Circuitsoft said:
    I can't help but wonder how hard it would be to use KonneX to generate OpenCL compute shader code. This feels like it would very well target high performance streaming processors like modern gpus.

    There's no reason why not, although you'd never get the same sort of performance as GPUs doing simple calculations. In order to make the best of the parallelism offered by KonneX, the code executed by each thread would have to do more. GPUs are like a printing press or sheet metal stamp. Load up the registers or RAM and "bang" they perform a single operation. KonneX would never be able to compete (sans GPU) even with 1000 cores at its disposal. However, when performing dissimilar operations, it would be able to do better.

  • GPUs are getting to be a lot more general than you may realize. Shadertoy.com is an interesting place to experiment with what shaders can do.

  • NixNix Posts: 18

    @Circuitsoft said:
    GPUs are getting to be a lot more general than you may realize. Shadertoy.com is an interesting place to experiment with what shaders can do.

    I really don't know what GPUs are capable of. For me, it is not a concern.
    Like any programming language, there is absolutely no reason why KonneX could not be used with them. They would be treated like any other device.
    Like conventional code, the driver would manage the loading, unloading of data and the triggering of the required operations. Whether these operations are single instructions or complete routines, is neither here nor there.
    The way I would envisage it, would be similar to the office photocopier with an operator. Staff would approach the operator with a bunch of paper to copy, together with instructions about quantity and collation. The operator would take these and schedule them in a queue. When each job was completed, the associated members of staff would be notified.

    In the same way, utilising the GPU would be a case of calling the GPU library with a bunch of data and the desired operation, with a single block dragged on to the drawing board. When executed, the calling code would simply wait until the operation was complete, before continuing.

  • NixNix Posts: 18
    edited 2021-09-10 20:09

    Ok.... 101 views to go until I reach 1K... keep the questions coming.
    I'm currently trying to create an animated video to describe how it works.

Sign In or Register to comment.