I am looking to speed up my automation which will try to ocr/classify/extract hundreds of files. currently we do it sequentially and yes we can add a couple more nodes but is there a way to “split and aggregate” the tasks via a pool of threads / processes in UiPath where i kick off the process for 10 files at a time and then gather the results? Like java executor framework or a C# threadpool ? i looked into parallel activity but it seemed more like a design time thing than run time. Any help is appreciated.
Hi @Venu_S,
One alternative here would be to set your process to run as a Background Process. Here I am assuming you do not have any UI interaction requirements in the same process. If the process uses UI interaction in another part of the process you have to scale horizontally on machine level.
This will mean that if you can scale your process in the same machine. For example if you have 3 unattended unused licenses , you can run 3 instances of your «background process» in the same machine. UiRobot.exe will run 3 dedicated instances.
Refer the below links on background process execution:
If this does not work for you, another alternative is to separate your OCR and UI interaction logic in the process to two dedicated processes. This will ensure you have better execution controls.
Thanks @jeevith for looking into this and the detail. I dont have a UI interaction so that is one less complication. This solution does seem to work for me but the caveat might be the aggregate piece of it. i would still like to be able to gather the results of each of these parallel operations and with this approach, i would need some kind of persistence to consolidate the results of the background runs. The cool thing about these multithreading frameworks is they will let you update some kind of synchronized list for result aggregation. So there is nothing in UI path that allows for this paradigm right? Just want to exhaust the possibility.
Unfortunately yes this is what you will have to stitch up on your own with a background process. I don’t see any other way in UiPath to achieve your requirements.
A process with consolidation output is sadly going to be clumbersome to implement and may need some additional testing. For example if the bot fails one day guardrails have to be in place so as to not to use outputs from previous runs etc.
To avoid any IO issues while writing the temporary content to a file (output from one execution) I would keep a 1 is to 1 relationship. Each process writes to a dedicated file and later use another background process to combine the outputs say CSVs or JSON files to one output file.
Or same can be achieved with dedicated n number of text assets in Orchestrator and each execution writes to its corresponding asset. A final process (n+1th process) which combines the three assets to give you the consolidated output.
In both scenarios you will have to also consider how to reset the content depending on your business logic to avoid duplication of output.
It is a good usecase to submit as a feedback to UiPath by adding a new topic here:
Probably you can also evaluate if UiPath is the right tool for this use case. May be other programming languages and use the multithreaded functions as you mentioned above may be a better fit? Again this alternative will have its own pros and cons.
Hi @jeevith thanks for the ideas, i whipped up a simple C# program that does it. it seems to be doing about 40% better than single threading although i was expecting more . The json to make an ocr call is below. it seems to work for a single base64 encoded image. Also i have just used a generic threadpool, i am not sure if C# will support an exclusive threadpool but will be an improvement if we can get it. Some work can be done around exception handling and timeout but the general idea should remain
Header
X-UIPATH-License : <ocrlicencw>
Body
{
"requests : [{
“image” : {“content” : “”},
“features” : [
{“type” : “TextDetection”}
],
“imageContext” : {
“languageHints” : [“auto”]
}
}]
}
// Controls the number of threads to be run in parallel
int numberOfParallel = 10;
string jsonContent = “the json above”;
string url = "http://ocrurl/du-ocr”;
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(url);
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(“application/json”));
var countDownEvents = new CountdownEvent(numberOfParallel);
ConcurrentBag aggregate = new ConcurrentBag();
Func multiThread = () =>
{
Action makeOcrCall = delegate (object state)
{
StringContent jsonStringContent = new StringContent(jsonContent, Encoding.UTF8, “application/json”);
HttpResponseMessage postResponse = httpClient.PostAsync(url).Result;
if (postResponse.IsSuccessStatusCode)
{
string result = postResponse.Content.ReadAsStringAsync().Result;
Console.WriteLine(result);
}
else
{
Thread.Sleep(5000);
Console.WriteLine(“failed {0}”, postResponse.StatusCode);
aggregate.Add(“failed {0}”);
}
postResponse.Dispose();
countDownEvents.Signal();
};
for (int i = 0; i < numberOfParallel; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(makeOcrCall), i);
}
countDownEvents.Wait();
return "";
};
multiThread();