{ "cells": [ { "cell_type": "markdown", "id": "bdb6b8e0", "metadata": {}, "source": [ "# mt_fillNtuples\n", "Fill n-tuples in distinct workers.\n", "This tutorial illustrates the basics of how it's possible with ROOT to\n", "offload heavy operations on multiple threads and how it's possible to write\n", "simultaneously multiple files. The operation performed in this case is the\n", "creation of random gaussian numbers.\n", "\n", "\n", "\n", "\n", "**Author:** Danilo Piparo \n", "This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, May 19, 2026 at 08:17 PM." ] }, { "cell_type": "code", "execution_count": 1, "id": "a0299e52", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:25.204205Z", "iopub.status.busy": "2026-05-19T20:17:25.204093Z", "iopub.status.idle": "2026-05-19T20:17:25.520479Z", "shell.execute_reply": "2026-05-19T20:17:25.519751Z" } }, "outputs": [], "source": [ "const UInt_t nNumbers = 20000000U;\n", "\n", "const UInt_t nWorkers = 4U;\n", "\n", "const auto workSize = nNumbers / nWorkers;" ] }, { "cell_type": "markdown", "id": "a68cfa0f", "metadata": {}, "source": [ " Some useful constants and functions\n", "Total amount of numbers\n", "The number of workers\n", "We split the work in equal parts\n", "A simple function to fill ntuples randomly\n", " " ] }, { "cell_type": "code", "execution_count": 2, "id": "97409bd6", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:25.522745Z", "iopub.status.busy": "2026-05-19T20:17:25.522601Z", "iopub.status.idle": "2026-05-19T20:17:25.535450Z", "shell.execute_reply": "2026-05-19T20:17:25.534938Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "void fillRandom(TNtuple &ntuple, TRandom3 &rndm, UInt_t n)\n", "{\n", " for (auto i : ROOT::TSeqI(n))\n", " ntuple.Fill(rndm.Gaus());\n", "}" ] }, { "cell_type": "markdown", "id": "956372ed", "metadata": {}, "source": [ "No nuisance for batch execution" ] }, { "cell_type": "code", "execution_count": 3, "id": "3cc131a4", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:25.536896Z", "iopub.status.busy": "2026-05-19T20:17:25.536772Z", "iopub.status.idle": "2026-05-19T20:17:25.742000Z", "shell.execute_reply": "2026-05-19T20:17:25.741276Z" } }, "outputs": [], "source": [ "gROOT->SetBatch();" ] }, { "cell_type": "markdown", "id": "dd424a9e", "metadata": {}, "source": [ "Perform the operation sequentially ---------------------------------------" ] }, { "cell_type": "markdown", "id": "52cc78e1", "metadata": {}, "source": [ "Create a random generator and and Ntuple to hold the numbers" ] }, { "cell_type": "code", "execution_count": 4, "id": "f332662f", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:25.744168Z", "iopub.status.busy": "2026-05-19T20:17:25.744047Z", "iopub.status.idle": "2026-05-19T20:17:28.074151Z", "shell.execute_reply": "2026-05-19T20:17:28.073468Z" } }, "outputs": [], "source": [ "TRandom3 rndm(1);\n", "TFile ofile(\"mt101_singleCore.root\", \"RECREATE\");\n", "TNtuple randomNumbers(\"singleCore\", \"Random Numbers\", \"r\");\n", "fillRandom(randomNumbers, rndm, nNumbers);\n", "randomNumbers.Write();\n", "ofile.Close();" ] }, { "cell_type": "markdown", "id": "43869eda", "metadata": {}, "source": [ "We now go MT! ------------------------------------------------------------" ] }, { "cell_type": "markdown", "id": "3f1f43f7", "metadata": {}, "source": [ "The first, fundamental operation to be performed in order to make ROOT\n", "thread-aware." ] }, { "cell_type": "code", "execution_count": 5, "id": "f711e1da", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:28.076492Z", "iopub.status.busy": "2026-05-19T20:17:28.076370Z", "iopub.status.idle": "2026-05-19T20:17:28.281305Z", "shell.execute_reply": "2026-05-19T20:17:28.280648Z" } }, "outputs": [], "source": [ "ROOT::EnableThreadSafety();" ] }, { "cell_type": "markdown", "id": "9911926d", "metadata": {}, "source": [ "We define our work item" ] }, { "cell_type": "code", "execution_count": 6, "id": "b2844ab1", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:28.283169Z", "iopub.status.busy": "2026-05-19T20:17:28.283050Z", "iopub.status.idle": "2026-05-19T20:17:28.485264Z", "shell.execute_reply": "2026-05-19T20:17:28.484549Z" } }, "outputs": [], "source": [ "auto workItem = [](UInt_t workerID) {\n", " // One generator, file and ntuple per worker\n", " TRandom3 workerRndm(workerID); // Change the seed\n", " TFile ofile(Form(\"mt101_multiCore_%u.root\", workerID), \"RECREATE\");\n", " TNtuple workerRandomNumbers(\"multiCore\", \"Random Numbers\", \"r\");\n", " fillRandom(workerRandomNumbers, workerRndm, workSize);\n", " workerRandomNumbers.Write();\n", " return 0;\n", "};" ] }, { "cell_type": "markdown", "id": "c57dca72", "metadata": {}, "source": [ "Create the collection which will hold the threads, our \"pool\"" ] }, { "cell_type": "code", "execution_count": 7, "id": "ef67140b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:28.487226Z", "iopub.status.busy": "2026-05-19T20:17:28.487105Z", "iopub.status.idle": "2026-05-19T20:17:28.692110Z", "shell.execute_reply": "2026-05-19T20:17:28.691437Z" } }, "outputs": [], "source": [ "std::vector workers;" ] }, { "cell_type": "markdown", "id": "b74642ff", "metadata": {}, "source": [ "Fill the \"pool\" with workers" ] }, { "cell_type": "code", "execution_count": 8, "id": "3832978b", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:28.694208Z", "iopub.status.busy": "2026-05-19T20:17:28.694091Z", "iopub.status.idle": "2026-05-19T20:17:28.896192Z", "shell.execute_reply": "2026-05-19T20:17:28.895520Z" } }, "outputs": [], "source": [ "for (auto workerID : ROOT::TSeqI(nWorkers)) {\n", " workers.emplace_back(workItem, workerID);\n", "}" ] }, { "cell_type": "markdown", "id": "6d1bf331", "metadata": {}, "source": [ "Now join them" ] }, { "cell_type": "code", "execution_count": 9, "id": "227627dd", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:28.898253Z", "iopub.status.busy": "2026-05-19T20:17:28.898134Z", "iopub.status.idle": "2026-05-19T20:17:29.477716Z", "shell.execute_reply": "2026-05-19T20:17:29.476865Z" } }, "outputs": [], "source": [ "for (auto &&worker : workers)\n", " worker.join();\n", "\n", "return 0;" ] }, { "cell_type": "markdown", "id": "6cf75ad4", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 10, "id": "37f65381", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:17:29.479689Z", "iopub.status.busy": "2026-05-19T20:17:29.479543Z", "iopub.status.idle": "2026-05-19T20:17:29.684702Z", "shell.execute_reply": "2026-05-19T20:17:29.683960Z" } }, "outputs": [], "source": [ "gROOT->GetListOfCanvases()->Draw()" ] } ], "metadata": { "kernelspec": { "display_name": "ROOT C++", "language": "c++", "name": "root" }, "language_info": { "codemirror_mode": "text/x-c++src", "file_extension": ".C", "mimetype": " text/x-c++src", "name": "c++" } }, "nbformat": 4, "nbformat_minor": 5 }