Multi-core usage information for Xojo

I dabbled a bit in using 2 processors a couple of years ago. A huge pain in the behind.

@Sam Rowlands: most of what you want to do is possible with multiple threads. Even that is pain enough.

@Ulrich Bogun: the management of handling background processes needs to be improved.

(Answer to Norman’s post above)

I don’t think the whole framework needs to be thread safe. It could start with tiny set, even if its just String and Basic flow operators then its a start. Then whichever class that would make sense could follow after that slowly.

I would guess it does because there is no ability to predict what people will/wont try to use in a multithreaded scenario.
(At least that was Joe’s feeling about it way back when)

Personally I’d like to see work done to make it easier to marshall data between a main and helpers because preemptive thresds are just hard to reason about OR you end up doing various tricks to synchronze them as various points waiting for each other to finish.
Helpers as a single stand alone entity can be tested independently in a manner you do not need to try & reason about what did/didnt get preempted etc

I didn’t want the discussion to digress into HOW it should be done, but since that appears to be what everyone wants to talk about.

I have a solution in my app that works how I want, but it’s not Xojo native, it’s using a different tool and integrates within Xojo via a custom plugin. I want to be able to do this with native Xojo. For background tasks I’d accept some limitations in regards to sharing data across contexts, but it should be done through data copies, and not serialization.


I created a memoryblock in Xojo and populated it with the data I needed to alter. To pass it to the plugin, I created a NSData object and explicitly told it NOT to copy the data (I wanted to be able to read it back from this object on completion), I also didn’t want to wait for the copy process.

In the plugin, I extracted the Ptr from the NSData object, adjusted it to the position I expected and did the work. Below is a sample of the code I’m using, it is so simple, that it’s astounding and yet completes the task in 1/7th of time.

[code]- (void) processData: (NSData *)imageData {
NSUInteger pixelCount = [imageData length] / 2;
char *baseBytes = (Ptr)[baseData mutableBytes];

dispatch_queue_t queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 );

NSUInteger stride = [blockSize unsignedIntegerValue];

dispatch_apply( pixelCount / stride, queue, ^(size_t idx) {
    size_t j = idx * stride;
    size_t j_stop = j + stride;
    
    do {
        // --- Actual data manipulation here.
        j++;
    } while ( j < j_stop );
});

size_t i;
for ( i = pixelCount - ( pixelCount % stride ); i < pixelCount; i++ ) {
   // --- Actual data manipulation here.
}

}[/code]

@Ulrich Bogun In following Thomas’ footsteps, the key looks like it’s done via blocks here, which are a little fragile in Xojo, but with some more thread safety, accomplishing this within Native Xojo looks possible. I’d need primitive type creation and looping, plus memoryblock access.

MBS Xojo Plugins 20.1pr5 is available for testing.
It includes EvaluateMT and CallFunctionMT methods for JavaScriptEngineMBS class.
So you could run javaScript functions in parallel on multiple preemptive threads.

<https://xojo.com/issue/58144>

Where did you get that information?

Please also see case <https://xojo.com/issue/53200>: ThreadSafeCallback pragma for callbacks

If we could mark thread safe routines and Xojo would mark thread safe methods in their framework, this would allow to use a subset of the language to be used in such callback methods.

[quote=476509:@Norman Palardy]I would guess it does because there is no ability to predict what people will/wont try to use in a multithreaded scenario.
(At least that was Joe’s feeling about it way back when)[/quote]
The IDE has method/property attributes, Shirley the compiler/linker can use these to detect when a function is marked as thread safe. Analyze project could then show which functions it believes are not thread safe, but it shouldn’t stop compiling or building incase the attribute was mistakenly not added.

someone would still have to go through the framework and mark all such routines in the framework
those are much more important to flag than OUR code IMHO
again this is not trivial to go through a be certain that all routines marked as such truly are - as once you mark them and they are used reverting that approval would raise the same kinds of howls that renaming events got - that I’m certain of

Look I get WHY people want preemptive threading - I just happen to believe its not the right mechanism to utilize multiple cores
Preemptive threading a seriously f*ing hard to reason about and debug (unless you put in all kinds of sync and waits between threads which means you might a well NOT use preemptive threads)

Making XojoScript able to be preemptively scheduled would get a LOT of the way there - and ALL access is already sandboxed in a way that using a context object and its methods already guards us all from ripping our eyes out trying to debug preemptive threads.

Or making it easier to write a helper AND main app in one project (see my blog post about Universal Projects) where common code would be usable in both project simply. Marshalling data back and forth would still be THE issue - but even that can be done quite efficiently and quickly using shared memory (talk to Peter Stys about this)

Passing objects or references to them would - in both cases - still be forbidden but personally I’d be ok with that since thats the part that is really hard to reason about in a preemptive programming model.

IF were ever going to see preemptive / multi-core apps it has to be done in a “Xojo way” which means fairly safely for the average user to make sue of without having to have a PhD in CompSci.

XojoScript and /or easier helper apps is the most likely way to get there from here

Norman,
I appreciate your point of view, especially as I know your background, and through the many conversations that we’ve had over this topic, and please understand that I absolutely do not mean to offend or upset you, even if what I write might seem like it.

You know how much work it is to do this in pure Xojo, I am sure that Xojo know how challenging it currently is also. But I persisted and fought through, even dealing with other restrictions that the App Store impose, trying to squeeze more performance out of my apps. It’s a demoralizing bad minefield of work v.s. improvement, but hey, that’s kind of the overall opinion of macOS development nowadays.

I admire @Peter Stys for his persistence, more so because he and I are trying to accomplish the same thing, which is to process images as fast as possible.

When I decided to attempt this with a different tool, I went in expecting all kinds of problems and a general “spend a lot of time/little progress” situation. Which is exactly the opposite of what I got. I can’t emphasize enough how simple it was, and how eye opening that multi-core programming isn’t as difficult as I believed it to be. The first time I tried to run the code (in a language that I am not as well versed as Xojo) it just worked. I had to tweak it to find the best balance of task per core, but it worked.

Which is why I have shared the core code that it took, obviously it’s missing the actually image processing code and the wrapping code so that it can be called from within Xojo.

It is my understanding (and I can be completely wrong) that GCD utilizes blocks, which we can use in Xojo at the moment. However block access on non-main threads are very fragile. For Apple’s platforms, Xojo don’t need to re-invent the wheel, they just need to make their framework thread safe, and maybe not all of it. If they start small, and progress over time, it goes from being a task that isn’t started because it’s overwhelming to one day, being accomplished.

Hence why I started this very thread, to illustrate what I and others would need. The simplest of tasks that I want to improve performance would involve looping through a shared block of memory (each core would have only a range to loop through), reading numeric values, applying math to those values and putting them back.

Yes I can do this with helpers, but it took far longer to get all the pieces together to do that, than simply write the above code using an alternative tool.

There is also another reason as to why I am hoping for GCD adoption over helpers or “scripting languages”, I have a great deal of customers who have 45+ megapixel cameras, including one who uses a 100 megapixel Hassleblad. I do most of my processing in 128-BPP floating point, so these images can use a large amount of memory, for some of these cases I’ve elected to NOT use the GPU, because there is no way I know of how to test if there is enough memory available on the GPU (there are two other reasons as to why I am looking to do certain tasks on the CPU with machine RAM than via GPU), while in these cases all the customers have enough RAM. It makes most sense to allow each core based task to access to the same area of memory. The macOS supports two different mechanisms for sharing memory (that I am aware of), but the App Store only supports one, what happens if Apple decide for “Security & Privacy” to no longer allow this. My app is dead. Meanwhile I am pretty confident that GCD will continue to allow this (as it’s the same app).

I think I’ve flogged this dead horse long enough, the ball is in Xojo’s court now, hopefully with this information they’ll consider altering their framework and invest in providing functionality that will improve the performance of Xojo based apps.

1 Like

its interconnected internally in ways that might surprise you
If you want to deal with the Application class it requires folderitem (as it has folderitem properties), menu bar properties, etc
so a lot of code has to be thread safe to make Application work
so i can turn into a giant job VERY quickly

interestingly enough “for each” was envisioned at one time to be able to be parallelized exactly like this. Its one reason no guarantee of order was made. Could it still be parallelized ? probably when the compiler engineer and framework engineer get to it :stuck_out_tongue:

[quote=476743:@Sam Rowlands]Yes I can do this with helpers, but it took far longer to get all the pieces together to do that, than simply write the above code using an alternative tool.
[/quote]
granted - just that for the average Xojo user making this easier would go a LONG way
easier & safe would be really nice

well XojoScript IS xojo - its just sandboxed in a way its safe to likely run on its own core because all access to memory etc is brokered through the context object
You can do some interesting things with this configuration

I totally don’t understand what XojoScript is supposed to help here.

1 Like

I don’t think xojoscript is going to help with runtime code in memory issues. You all know how macOS works these days with it’s requirements. We don’t need more not-going-to-work features in xojo. We need a cross-platform workable solution, that is easy to implement.

XojoScript could be made to be preemptive and able to run each script on a different core
Because it already has sandboxed access to the main app (and resources that may need to be thread safe) its a decent candidate for being able to get to preemptive multi-core capabilities in a cross platform usable way in something less than a decade :slight_smile:

Its much more likely than say a platform specific thing like GCD

What can I do with XojoScript? I always thought that XojoScript is to make an app scriptable. It also remember that XojoScript can only talk to the main app in a very convoluted manner.

you would be surprised what you can do with a little ingenuity :slight_smile:
while you cannot pass objects or object references across the context boundary (which is what makes XojoScript basically already built to be thread safe) you can pass all the intrinsic types (strings, integers, doubles, etc) you CAN attach an object to the context and then expose it via methods on the context to the script.
its all a matter of planning

there are some OK examples in the Example > Projects > Advanced > XojoScript but they are far from the most sophisticated

so far the project I’m working on has many features that folks might be surprised to see in a XojoScript :slight_smile:

the access to the main app isnt “really convoluted” once you sit down and plan it out

The examples for XojoScript show me nothing.

you looked at the imaging one ?
Example > Projects > Advanced > XojoScript > Imaging > ScriptImaging.xojo_binary_project
that manipulates an image in XojoScript

I improved our JavaScriptEngineMBS class by allowed you to pass Memoryblock to JavaScript and work on it there:

[code]Try

// Pass Memoryblock To JavaScript via Variant To get buffer In JavaScript:

Dim m As New MemoryBlock(20)
je.GlobalProperty(“mem”) = m

Dim v As Variant = je.Evaluate(“for (i = 0; i < 10; i++) { mem[i] = i; }; mem.length;”)

List.AppendRow "result: "+Str(v.IntegerValue)

Dim mm As MemoryBlock = je.GlobalProperty(“mem”)
List.AddRow EncodeHex(mm)

Catch j As JavaScriptEngineExceptionMBS

List.AppendRow "Exception: "+j.Message

End Try[/code]

Combined with our new MT methods this would allow you to pass data to JavaScript and run it In preemptive thread.