Perpendicular: Parallel LUAU made easy!

Perpendicular: Parallel LUAU Wrapper

Takes advantage of the parallel luau feature on ROBLOX, intended for easy use. However easy, this module requires some pre-existing and extensive knowledge on Luau and Parallel Luau especially, I reccommend you check out this youtube video, by Suphi Kaner, if you are unfamiliar with the concept. Let me know about any features that I should add!

Brief Overview:

New ‘function instances’ are made off of the perpendicular module which calls on the actorClass, actors are cached for a specified amount of time before they are eventually deleted. All optimizations (to my knowledge) have been made, however, if you spot any, feel free to let me know.

DOCUMENTATION : ACTOR INSTANCE CREATION

It is demanded that you create a new actor instance with the function you wish to run, as the nature of Parallel Luau demands so. Creating modules and requiring those would be uneffective, as you would still need to create a new Actor Instance per each thread.

image

Any new functions should be made following a similar template to the image shown above, with a runScript and a runSignal within each Actor Instance. Editing the functions themselves should prove to be simple, documentation on that is shown below.

DOCUMENTATION : PERPENDICULAR

perpendicular.desyncFunction(functionName : string) : perpendicularObject

Creates a parallel function which runs the predetermined function under the actorClass → helpers folder. Returns a perpendicularObject.

perpendicularObject:run(...)

Runs the function, after its initial run the perpendicularObject is destroyed. Any parameters specified are run inside of the function of the Actor Instance.

perpendicularObject.completed : Event

Fires as soon as the ran function returns a value.

Example Usage

– > Perpendicular

local perpendicular = require(perpendicularPath)

local newFunction = perpendicular.desyncFunction("thisIsAFunction")

newFunction:run("return this string!")

newFunction.completed:Connect(function(message)
    print("newFunction has returned : "..message)
end)

– > thisIsAFunction

local runSignal = script.Parent:WaitForChild("runSignal")

local function thisIsAFunction(returning)
    return returning
end

runSignal.Event:ConnectParallel(function(pathway, ...)
    if pathway ~= "run" then return end
    runSignal:Fire("finished", thisIsAFunction(...))
end)

– > Output

newFunction has returned : return this string!

Download:

4 Likes

So with this, i can run my code in parallel and get the values that threads return?

1 Like

Essentially, but you gotta make sure to take into account the desynchronization that it causes, if you want you could also do perpendicularObject.completed:Wait() to wait until the value is returned.

I’m planning on implementing a feature for multi-threaded loops, basically splitting up, for example, a
for i = 1, 50 loop into:

1, 10
11, 20
21, 30
31, 40
41, 50

And having it return all the values :smiley:

Well, your multi-threaded loops idea is really good. I could use it for my Particles Module to get better performance and make it easier to use.

1 Like

I am 90% this is due to this update Deferred Engine Events: Rollout Update but now if you schedule a bunch of work using :ScheduleWork, and then immediately use :Work() this module breaks. I think is because the actors are created on the fly, but they don’t have their :ConnectParallel work until the frame after, and thus the first :ScheduleWork will break since the event is just nonexistant. Every :ScheduleWork after the first broken one works however since it’s just reusing the Actors from the previous attempt which have existed for longer than a frame and do have their :ConnectParallel set. If you also put a task.wait() it also fixes itself.

I edited the module script myself to make it generate all the actors as soon as it is required() (if you require and instantly schedulework it might still break, but in my use case that never happens, so I don’t care really)