{
"cells": [
{
"cell_type": "markdown",
"id": "0f4f498a",
"metadata": {},
"source": [
"# mt103_fillNtupleFromMultipleThreads\n",
"Fill the same TNtuple from different threads.\n",
"This tutorial illustrates the basics of how it's possible with ROOT\n",
"to write simultaneously to a single output file using TBufferMerger.\n",
"\n",
"\n",
"\n",
"\n",
"**Author:** Guilherme Amadio \n",
"This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, March 19, 2024 at 07:13 PM."
]
},
{
"cell_type": "markdown",
"id": "3a44103b",
"metadata": {},
"source": [
"Avoid unnecessary output"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "db913473",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:36.719694Z",
"iopub.status.busy": "2024-03-19T19:13:36.719232Z",
"iopub.status.idle": "2024-03-19T19:13:37.492714Z",
"shell.execute_reply": "2024-03-19T19:13:37.491613Z"
}
},
"outputs": [],
"source": [
"gROOT->SetBatch();"
]
},
{
"cell_type": "markdown",
"id": "5e4b18c6",
"metadata": {},
"source": [
"Make ROOT thread-safe"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "88f3173e",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:37.507777Z",
"iopub.status.busy": "2024-03-19T19:13:37.507405Z",
"iopub.status.idle": "2024-03-19T19:13:37.742646Z",
"shell.execute_reply": "2024-03-19T19:13:37.732683Z"
}
},
"outputs": [],
"source": [
"ROOT::EnableThreadSafety();"
]
},
{
"cell_type": "markdown",
"id": "ba0a2b06",
"metadata": {},
"source": [
"Total number of events"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "162cc867",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:37.748860Z",
"iopub.status.busy": "2024-03-19T19:13:37.748493Z",
"iopub.status.idle": "2024-03-19T19:13:37.974645Z",
"shell.execute_reply": "2024-03-19T19:13:37.973627Z"
}
},
"outputs": [],
"source": [
"const size_t nEntries = 65535;"
]
},
{
"cell_type": "markdown",
"id": "f876178a",
"metadata": {},
"source": [
"Match number of threads to what the hardware can do"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "bcc1dadb",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:38.007814Z",
"iopub.status.busy": "2024-03-19T19:13:38.007436Z",
"iopub.status.idle": "2024-03-19T19:13:38.230580Z",
"shell.execute_reply": "2024-03-19T19:13:38.229583Z"
}
},
"outputs": [],
"source": [
"const size_t nWorkers = 4;"
]
},
{
"cell_type": "markdown",
"id": "ad0bdedf",
"metadata": {},
"source": [
"Split work in equal parts"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "afb7de61",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:38.238450Z",
"iopub.status.busy": "2024-03-19T19:13:38.238058Z",
"iopub.status.idle": "2024-03-19T19:13:38.454400Z",
"shell.execute_reply": "2024-03-19T19:13:38.453066Z"
}
},
"outputs": [],
"source": [
"const size_t nEventsPerWorker = nEntries / nWorkers;"
]
},
{
"cell_type": "markdown",
"id": "bef41cda",
"metadata": {},
"source": [
"Create the TBufferMerger: this class orchestrates the parallel writing"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "09e3a863",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:38.458823Z",
"iopub.status.busy": "2024-03-19T19:13:38.458443Z",
"iopub.status.idle": "2024-03-19T19:13:38.675104Z",
"shell.execute_reply": "2024-03-19T19:13:38.674041Z"
}
},
"outputs": [],
"source": [
"auto fileName = \"mt103_fillNtupleFromMultipleThreads.root\";\n",
"ROOT::TBufferMerger merger(fileName);"
]
},
{
"cell_type": "markdown",
"id": "4a5785be",
"metadata": {},
"source": [
"Define what each worker will do\n",
"We obtain from a merger a TBufferMergerFile, which is nothing more than\n",
"a file which is held in memory and that flushes to the TBufferMerger its\n",
"content."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "5c463738",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:38.682842Z",
"iopub.status.busy": "2024-03-19T19:13:38.682482Z",
"iopub.status.idle": "2024-03-19T19:13:38.892249Z",
"shell.execute_reply": "2024-03-19T19:13:38.891342Z"
}
},
"outputs": [],
"source": [
"auto work_function = [&](int seed) {\n",
" auto f = merger.GetFile();\n",
" TNtuple ntrand(\"ntrand\", \"Random Numbers\", \"r\");\n",
"\n",
" TRandom rnd(seed);\n",
" for (auto i : ROOT::TSeqI(nEntries))\n",
" ntrand.Fill(rnd.Gaus());\n",
" f->Write();\n",
"};"
]
},
{
"cell_type": "markdown",
"id": "b44c6679",
"metadata": {},
"source": [
"Create worker threads"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "cb5e92aa",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:38.919238Z",
"iopub.status.busy": "2024-03-19T19:13:38.918839Z",
"iopub.status.idle": "2024-03-19T19:13:39.574653Z",
"shell.execute_reply": "2024-03-19T19:13:39.573674Z"
}
},
"outputs": [],
"source": [
"std::vector workers;\n",
"\n",
"for (auto i : ROOT::TSeqI(nWorkers))\n",
" workers.emplace_back(work_function, i + 1); // seed==0 means random seed :)\n",
"\n",
"// Make sure workers are done\n",
"for (auto &&worker : workers)\n",
" worker.join();"
]
},
{
"cell_type": "markdown",
"id": "388036b0",
"metadata": {},
"source": [
"Draw all canvases "
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "3badbada",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2024-03-19T19:13:39.586768Z",
"iopub.status.busy": "2024-03-19T19:13:39.586392Z",
"iopub.status.idle": "2024-03-19T19:13:39.872466Z",
"shell.execute_reply": "2024-03-19T19:13:39.817972Z"
}
},
"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
}