Skip to content

Commit fdeb4c3

Browse files
Distribute changes to the src/ files as comments
1 parent 1b5b1eb commit fdeb4c3

File tree

15 files changed

+95
-105
lines changed

15 files changed

+95
-105
lines changed

man/openmp-utils.Rd

Lines changed: 5 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -38,121 +38,22 @@
3838
3939
\itemize{
4040
\item\file{between.c} - \code{\link{between}()}
41-
42-
OpenMP is used here to parallelize:
43-
\itemize{
44-
\item The loops that check if each element of the vector provided is between the specified \code{lower} and \code{upper} bounds, for integer (\code{INTSXP}) and real (\code{REALSXP}) types
45-
\item The checking and handling of undefined values (such as NaNs)
46-
}
47-
48-
Since this function is used to find rows where a column's value falls within a specific range, it benefits more from parallelization when the input data consists of a large number of rows.
49-
5041
\item\file{cj.c} - \code{\link{CJ}()}
51-
52-
OpenMP is used here to parallelize:
53-
54-
\itemize{
55-
\item The element assignment in vectors
56-
\item The memory copying operations (blockwise replication of data using \code{memcpy})
57-
\item The creation of all combinations of the input vectors over the cross-product space
58-
}
59-
60-
Given that the number of combinations increases exponentially as more columns are added, better speedup can be expected when dealing with a large number of columns.
61-
6242
\item\file{coalesce.c} - \code{\link{fcoalesce}()}
63-
64-
OpenMP is used here to parallelize:
65-
\itemize{
66-
\item The operation that iterates over the rows to coalesce the data (which can be of type integer, real, or complex)
67-
\item The replacement of NAs with non-NA values from subsequent vectors
68-
\item The conditional checks within parallelized loops
69-
}
70-
71-
Significant speedup can be expected for more number of columns here, given that this function operates efficiently across multiple columns to find non-NA values.
72-
7343
\item\file{fifelse.c} - \code{\link{fifelse}()}
74-
75-
For logical, integer, and real types, OpenMP is being used here to parallelize loops that perform conditional checks along with assignment operations over the elements of the supplied logical vector based on the condition (\code{test}) and values provided for the remaining arguments (\code{yes}, \code{no}, and \code{na}).
76-
77-
Better speedup can be expected for more number of columns here as well, given that this function operates column-wise with independent vector operations.
78-
79-
\item\file{fread.c} - \code{\link{fread}()}
80-
81-
OpenMP is used here to:
82-
83-
\itemize{
84-
\item Parallelize the reading of data in chunks
85-
\item Avoid race conditions or concurrent writes to the output \code{data.table} by having atomic operations on the string data
86-
\item Manage synchronized updates to the progress bar and serialize the output to the console
87-
}
88-
89-
This function is highly optimized in reading and processing data with both large numbers of rows and columns, but the efficiency is more pronounced across rows.
90-
44+
\item\file{fread.c} - \code{\link{fread}(). Parallelized across row-based chunks of the file.}
9145
\item\file{forder.c}, \file{fsort.c}, and \file{reorder.c} - \code{\link{forder}()} and related
92-
93-
OpenMP is used here to parallelize multiple operations that come together to sort a \code{data.table} using the Radix algorithm. These include:
94-
95-
\itemize{
96-
\item The counting of unique values and recursively sorting subsets of data across different threads (specific to \file{forder.c})
97-
\item The process of finding the range and distribution of data for efficient grouping and sorting (applies to both \file{forder.c} and \file{fsort.c})
98-
\item Creation of histograms which are used to sort data based on significant bits (each thread processes a separate batch of the data, computes the MSB of each element, and then increments the corresponding bins), with the distribution and merging of buckets (specific to \file{fsort.c})
99-
\item The process of reordering a vector or each column in a list of vectors (such as in a \code{data.table}) based on a given vector that dictates the new ordering of elements (specific to \file{reorder.c})
100-
}
101-
102-
Better speedups can be expected when the input data contains a large number of rows as the sorting complexity increases with more rows.
103-
10446
\item\file{froll.c}, \file{frolladaptive.c}, and \file{frollR.c} - \code{\link{froll}()} and family
105-
106-
OpenMP is used here to parallelize the loops that compute the rolling means (\code{frollmean}) and sums (\code{frollsum}) over a sliding window for each position in the input vector.
107-
108-
These functions benefit more in terms of speedup when the data has a large number of columns, primarily due to the efficient memory access patterns (cache-friendly) used when processing the data for each column sequentially in memory to compute the rolling statistic.
109-
110-
\item\file{fwrite.c} - \code{\link{fwrite}()}
111-
112-
OpenMP is used here primarily to parallelize the process of writing rows to the output file, but error handling and compression (if enabled) are also managed within the parallel region. Special attention is paid to thread safety and synchronization, especially in the ordered sections where output to the file and handling of errors is serialized to maintain the correct sequence of rows.
113-
114-
Similar to \code{\link{fread}()}, this function is highly efficient in parallely processing data with large numbers of both rows and columns, but it has more notable speedups with an increased number of rows.
115-
116-
\item\file{gsumm.c} - GForce in various places, see \link{GForce}
117-
118-
Functions with GForce optimization are internally parallelized to speed up grouped summaries over a large \code{data.table}. OpenMP is used here to parallelize operations involved in calculating group-wise statistics like sum, mean, and median (implying faster computation of \code{sd}, \code{var}, and \code{prod} as well).
119-
120-
These optimized grouping operations benefit more in terms of speedup if the input data contains a large number of groups since they leverage parallelization more efficiently by eliminating the overhead of individual group evaluations.
121-
47+
\item\file{fwrite.c} - \code{\link{fwrite}(). Parallelized across rows.}
48+
\item\file{gsumm.c} - GForce in various places, see \link{GForce}. Parallelized across groups.
12249
\item\file{nafill.c} - \code{\link{nafill}()}
123-
124-
OpenMP is being used here to parallelize the loop that fills missing values over columns of the input data. This includes handling different data types (double, integer, and integer64) and applying the designated filling method (constant, last observation carried forward, or next observation carried backward) to each column in parallel.
125-
126-
Given its optimization for column-wise operations, better speedups can be expected when the input data consists of a large number of columns.
127-
12850
\item\file{subset.c} - Used in \code{\link[=data.table]{[.data.table}} subsetting
129-
130-
OpenMP is used here to parallelize the loops that perform the subsetting of vectors, with conditional checks and filtering of data.
131-
132-
Since subset operations tend to be usually row-dependent, better speedups can be expected when dealing with a large number of rows. However, it also depends on whether the computations are focused on rows or columns (as dictated by the subsetting criteria).
133-
13451
\item\file{types.c} - Internal testing usage
135-
136-
This caters to internal tests (not impacting any user-facing operations or functions), and OpenMP is being used here to test a message printing function inside a nested loop which has been collapsed into a single loop of the combined iteration space using \code{collapse(2)}, along with specification of dynamic scheduling for distributing the iterations in a way that can balance the workload among the threads.
13752
}
13853
139-
In general, or as applicable to all the aforementioned use cases, better speedup can be expected when dealing with large datasets.
140-
141-
Having such data when using \code{\link{fread}()} or \code{\link{fwrite}()} (ones with significant speedups for larger file sizes) also means that while one part of the data is being read from or written to disk (I/O operations), another part can be simultaneously processed using multiple cores (parallel computations). This overlap reduces the total time taken for the read or write operation (as the system can perform computations during otherwise idle I/O time).
142-
143-
Apart from increasing the size of the input data, function-specific parameters when considered can benefit more from parallelization or lead to an increase in speedup. For instance, these can be:
144-
145-
\itemize{
146-
\item Having a large number of groups when using \code{\link{forder}()} or a multitude of combinations when using \code{\link{CJ}()}
147-
\item Having several missing values in your data when using \code{\link{fcoalesce}()} or \code{\link{nafill}()}
148-
\item Using larger window sizes and/or time series data when using \code{\link{froll}()}
149-
\item Having more and/or complex conditional logic when using \code{\link{fifelse}()} or \code{\link{subset}()}
150-
}
151-
152-
Note: The information above is based on implementation-specific details as of March 2024.
153-
54+
We endeavor to keep this list up to date, but note that the canonical reference here is the source code itself.
15455
}
15556
15657
\examples{
15758
getDTthreads(verbose=TRUE)
158-
}
59+
}

src/between.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include "data.table.h"
22

3+
/*
4+
OpenMP is used here to parallelize:
5+
- The loops that check if each element of the vector provided is between
6+
the specified lower and upper bounds, for INTSXP and REALSXP types
7+
- The checking and handling of undefined values (such as NaNs)
8+
*/
39
SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, SEXP checkArg) {
410
int nprotect = 0;
511
R_len_t nx = length(x), nl = length(lower), nu = length(upper);

src/cj.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include "data.table.h"
22

3+
/*
4+
OpenMP is used here to parallelize:
5+
- The element assignment in vectors
6+
- The memory copying operations (blockwise replication of data using memcpy)
7+
- The creation of all combinations of the input vectors over the cross-product space
8+
*/
39
SEXP cj(SEXP base_list) {
410
int ncol = LENGTH(base_list);
511
SEXP out = PROTECT(allocVector(VECSXP, ncol));

src/coalesce.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include "data.table.h"
22

3+
/*
4+
OpenMP is used here to parallelize:
5+
- The operation that iterates over the rows to coalesce the data
6+
- The replacement of NAs with non-NA values from subsequent vectors
7+
- The conditional checks within parallelized loops
8+
*/
39
SEXP coalesce(SEXP x, SEXP inplaceArg) {
410
if (TYPEOF(x)!=VECSXP) internal_error(__func__, "input is list(...) at R level"); // # nocov
511
if (!IS_TRUE_OR_FALSE(inplaceArg)) internal_error(__func__, "argument 'inplaceArg' must be TRUE or FALSE"); // # nocov

src/fifelse.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include "data.table.h"
22

3+
/*
4+
OpenMP is being used here to parallelize loops that perform conditional
5+
checks along with assignment operations over the elements of the
6+
supplied logical vector based on the condition (test) and values
7+
provided for the remaining arguments (yes, no, and na).
8+
*/
39
SEXP fifelseR(SEXP l, SEXP a, SEXP b, SEXP na) {
410
if (!isLogical(l)) {
511
error(_("Argument 'test' must be logical."));

src/forder.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,19 @@ uint64_t dtwiddle(double x) //const void *p, int i)
433433

434434
void radix_r(const int from, const int to, const int radix);
435435

436+
/*
437+
OpenMP is used here to parallelize multiple operations that come together to
438+
sort a data.table using the Radix algorithm. These include:
439+
440+
- The counting of unique values and recursively sorting subsets of data
441+
across different threads
442+
- The process of finding the range and distribution of data for efficient
443+
grouping and sorting
444+
- Creation of histograms which are used to sort data based on significant
445+
bits (each thread processes a separate batch of the data, computes the
446+
MSB of each element, and then increments the corresponding bins), with
447+
the distribution and merging of buckets
448+
*/
436449
SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP sortGroupsArg, SEXP ascArg, SEXP naArg)
437450
// sortGroups TRUE from setkey and regular forder, FALSE from by= for efficiency so strings don't have to be sorted and can be left in appearance order
438451
// when sortGroups is TRUE, ascArg contains +1/-1 for ascending/descending of each by column; when FALSE ascArg is ignored

src/fread.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,14 @@ static int detect_types( const char **pch, int8_t type[], int ncol, bool *bumped
12681268
//
12691269
// Returns 1 if it finishes successfully, and 0 otherwise.
12701270
//
1271+
// OpenMP is used here to:
1272+
// - Parallelize the reading of data in chunks
1273+
// - Avoid race conditions or concurrent writes to the output data.table by having atomic
1274+
// operations on the string data
1275+
// - Manage synchronized updates to the progress bar and serialize the output to the console
1276+
// This function is highly optimized in reading and processing data with both large numbers of
1277+
// rows and columns, but the efficiency is more pronounced across rows.
1278+
//
12711279
//=================================================================================================
12721280
int freadMain(freadMainArgs _args) {
12731281
args = _args; // assign to global for use by DTPRINT() in other functions

src/froll.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
#include "data.table.h"
22

3+
/*
4+
OpenMP is used here to parallelize the loops in frollmean and frollsum.
5+
6+
These functions benefit more in terms of speedup when the data has a large
7+
number of columns, primarily due to the efficient memory access patterns
8+
(cache-friendly) used when processing the data for each column
9+
sequentially in memory to compute the rolling statistic.
10+
*/
11+
312
/* fast rolling mean - router
413
* early stopping for window bigger than input
514
* also handles 'align' in single place

src/fsort.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ int qsort_cmp(const void *a, const void *b) {
9898
return (x<y)-(x>y); // largest first in a safe branchless way casting long to int
9999
}
100100

101+
/*
102+
OpenMP is used here to find the range and distribution of data for efficient
103+
grouping and sorting.
104+
*/
101105
SEXP fsort(SEXP x, SEXP verboseArg) {
102106
double t[10];
103107
t[0] = wallclock();

src/fwrite.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,14 @@ int compressbuff(z_stream *stream, void* dest, size_t *destLen, const void* sour
587587
}
588588
#endif
589589

590+
/*
591+
OpenMP is used here primarily to parallelize the process of writing rows
592+
to the output file, but error handling and compression (if enabled) are
593+
also managed within the parallel region. Special attention is paid to
594+
thread safety and synchronization, especially in the ordered sections
595+
where output to the file and handling of errors is serialized to maintain
596+
the correct sequence of rows.
597+
*/
590598
void fwriteMain(fwriteMainArgs args)
591599
{
592600
double startTime = wallclock();

0 commit comments

Comments
 (0)