-
Notifications
You must be signed in to change notification settings - Fork 3
Make code safe for large (>2G) buffers #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ae046e6
9a22bf5
2dc8e3b
f3f270f
e56adbd
a10a7e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,7 +81,7 @@ void nmat_detvecs_apply(const bp::object & ft, const bp::object & bins, const bp | |
| //#pragma omp parallel for | ||
| for(int di = 0; di < ndet; di++) | ||
| for(int i = b1; i < b2; i++) | ||
| ft_[di*nmode+i] *= biD[di]/norm; | ||
| ft_[(int64_t)(di*nmode+i)] *= biD[di]/norm; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sufficient ... must cast one of the multiplicands directly; e.g. Note also that |
||
| // Do ft += s*iV[ndet,nvec] dot Q [nvec,nm] | ||
| cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, ndet, nm, nvec, s/norm, biV, nvec, Q, nm, 1.0f, ft_+b1, nmode); | ||
| delete [] Q; | ||
|
|
@@ -250,22 +250,22 @@ void pcut_full_tod2vals_helper(const vector<RangesInt32> & rangemat, T * tod, in | |
| for(int di = 0; di < rangemat.size(); di++) | ||
| for (auto const &r: rangemat[di].segments) | ||
| for(int j = r.first; j < r.second; j++, i++) | ||
| vals[i] = tod[di*nsamp+j]; | ||
| vals[i] = tod[(int64_t)(di*nsamp+j)]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same -- apply the cast to di. |
||
| } | ||
| template <typename T> | ||
| void pcut_full_vals2tod_helper(const vector<RangesInt32> & rangemat, T * tod, int nsamp, T * vals) { | ||
| int i = 0; | ||
| for(int di = 0; di < rangemat.size(); di++) | ||
| for (auto const &r: rangemat[di].segments) | ||
| for(int j = r.first; j < r.second; j++, i++) | ||
| tod[di*nsamp+j] = vals[i]; | ||
| tod[(int64_t)(di*nsamp+j)] = vals[i]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same. |
||
| } | ||
|
|
||
| template <typename T> | ||
| void pcut_full_translate_helper(const vector<RangesInt32> & iranges, const vector<RangesInt32> & oranges, int insamp, T * ivals, int onsamp, T * ovals) { | ||
| // Translate cut degrees of freedom from one sample rate to another. | ||
| // Simple interpolation for upscaling, averaging when downscaling | ||
| int ioff = 0, ooff = 0; | ||
| int64_t ioff = 0, ooff = 0; | ||
| for(int di = 0; di < iranges.size(); di++) { | ||
| for(int ri = 0; ri < iranges[di].segments.size(); ri++) { | ||
| auto const & irange = iranges[di].segments[ri]; | ||
|
|
@@ -306,7 +306,7 @@ int pcut_poly_measure_helper(const vector<RangesInt32> & rangemat, int resolutio | |
| } | ||
| template <typename T> | ||
| void pcut_poly_tod2vals_helper(const vector<RangesInt32> & rangemat, int resolution, int nmax, T * tod, int nsamp, T * vals) { | ||
| int i = 0; | ||
| int64_t i = 0; | ||
| for(int di = 0; di < rangemat.size(); di++) { | ||
| for (auto const &r: rangemat[di].segments) { | ||
| int np = get_npoly(r.second-r.first, resolution, nmax); | ||
|
|
@@ -318,7 +318,7 @@ void pcut_poly_tod2vals_helper(const vector<RangesInt32> & rangemat, int resolut | |
| for(int p = 0; p < np; p++) vals[i+p] = 0; | ||
| for(int s = r.first; s < r.second; s++) { | ||
| T x = -1 + 2*(s-r.first)/T(r.second-r.first-1); | ||
| T t = tod[di*nsamp+s]; | ||
| T t = tod[(int64_t)(di*nsamp+s)]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same In all of these disjoint loops over detectors, I think it's simpler to compute a local pointer and use that. The compiler will optimize it to the same thing, but it keeps things cleaner. i.e. |
||
| vals[i] += t; | ||
| if(np > 1) vals[i+1] += t*x; | ||
| if(np > 2) { | ||
|
|
@@ -336,7 +336,7 @@ void pcut_poly_tod2vals_helper(const vector<RangesInt32> & rangemat, int resolut | |
| } | ||
| template <typename T> | ||
| void pcut_poly_vals2tod_helper(const vector<RangesInt32> & rangemat, int resolution, int nmax, T * tod, int nsamp, T * vals) { | ||
| int i = 0; | ||
| int64_t i = 0; | ||
| for(int di = 0; di < rangemat.size(); di++) { | ||
| for (auto const &r: rangemat[di].segments) { | ||
| int np = get_npoly(r.second-r.first, resolution, nmax); | ||
|
|
@@ -376,7 +376,7 @@ template <typename T> | |
| void pcut_poly_translate_helper(const vector<RangesInt32> & iranges, const vector<RangesInt32> & oranges, int resolution, int nmax, int insamp, T * ivals, int onsamp, T * ovals) { | ||
| // Translate cut degrees of freedom from one sample rate to another. | ||
| // Zero-pad poly coeffs if upsampling, truncate if downsampling | ||
| int ioff = 0, ooff = 0; | ||
| int64_t ioff = 0, ooff = 0; | ||
| for(int di = 0; di < iranges.size(); di++) { | ||
| for(int ri = 0; ri < iranges[di].segments.size(); ri++) { | ||
| auto const & irange = iranges[di].segments[ri]; | ||
|
|
@@ -596,12 +596,12 @@ void _moment(T* data, T* output, int moment, bool central, int64_t start, int64_ | |
| val = center; | ||
| } | ||
| else { | ||
| for(int si = start; si < stop; si++) { | ||
| for(int64_t si = start; si < stop; si++) { | ||
| val = val + pow(data[si] - center, moment); | ||
| } | ||
| val = val / bsize; | ||
| } | ||
| for(int si = start; si < stop; si++) { | ||
| for(int64_t si = start; si < stop; si++) { | ||
| output[si] = val; | ||
| } | ||
|
|
||
|
|
@@ -620,7 +620,7 @@ void _block_moment(T* tod_data, T* output, int bsize, int moment, bool central, | |
| _moment(tod_data, output, moment, central, ioff, ioff+shift); | ||
| } | ||
|
|
||
| for(int bi = 0; bi < nblock; bi++) { | ||
| for(int64_t bi = 0; bi < nblock; bi++) { | ||
| int64_t start = (bi * bsize) + shift; | ||
| int64_t stop = min(start + bsize, (int64_t)nsamp); | ||
| _moment(tod_data, output, moment, central, ioff+start, ioff+stop); | ||
|
|
@@ -659,7 +659,7 @@ void _minmax(T* data, T* output, int mode, int64_t start, int64_t stop) | |
| auto max = std::max_element(data+start, data+stop); | ||
| val = *max - *min; | ||
| } | ||
| for(int si = start; si < stop; si++) { | ||
| for(int64_t si = start; si < stop; si++) { | ||
| output[si] = val; | ||
| } | ||
|
|
||
|
|
@@ -678,7 +678,7 @@ void _block_minmax(T* tod_data, T* output, int bsize, int mode, int ndet, int ns | |
| _minmax(tod_data, output, mode, ioff, ioff+shift); | ||
| } | ||
|
|
||
| for(int bi = 0; bi < nblock; bi++) { | ||
| for(int64_t bi = 0; bi < nblock; bi++) { | ||
| int64_t start = (bi * bsize) + shift; | ||
| int64_t stop = min(start + bsize, (int64_t)nsamp); | ||
| _minmax(tod_data, output, mode, ioff+start, ioff+stop); | ||
|
|
@@ -715,7 +715,7 @@ void _clean_flag(int* flag_data, int width, int ndet, int nsamp) | |
| if(det_flag[si]==0) { | ||
| // If this block was too small | ||
| if(count<width) { | ||
| for(int i = si - count; i < si; i++){ | ||
| for(int64_t i = si - count; i < si; i++){ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Odd to change this type, but not |
||
| det_flag[i] = 0; | ||
| } | ||
| } | ||
|
|
@@ -1018,9 +1018,9 @@ void _interp1d(const bp::object & x, const bp::object & y, const bp::object & x_ | |
| #pragma omp for | ||
| for (int row = 0; row < n_rows; ++row) { | ||
|
|
||
| int y_row_start = row * y_data_stride; | ||
| int y_row_end = y_row_start + n_x; | ||
| int y_interp_row_start = row * y_interp_data_stride; | ||
| int64_t y_row_start = row * y_data_stride; | ||
| int64_t y_row_end = y_row_start + n_x; | ||
| int64_t y_interp_row_start = row * y_interp_data_stride; | ||
|
|
||
| T* y_row = y_data + y_row_start; | ||
| T* y_interp_row = y_interp_data + y_interp_row_start; | ||
|
|
@@ -1057,9 +1057,9 @@ void _interp1d(const bp::object & x, const bp::object & y, const bp::object & x_ | |
| #pragma omp for | ||
| for (int row = 0; row < n_rows; ++row) { | ||
|
|
||
| int y_row_start = row * y_data_stride; | ||
| int y_row_end = y_row_start + n_x; | ||
| int y_interp_row_start = row * y_interp_data_stride; | ||
| int64_t y_row_start = row * y_data_stride; | ||
| int64_t y_row_end = y_row_start + n_x; | ||
| int64_t y_interp_row_start = row * y_interp_data_stride; | ||
|
|
||
| // Transform y row to double array for gsl | ||
| double y_dbl[n_x]; | ||
|
|
@@ -1133,7 +1133,7 @@ void _detrend(T* data, const int ndets, const int nsamps, const int row_stride, | |
| if (method == "mean") { | ||
| #pragma omp parallel for num_threads(nthreads) | ||
| for (int i = 0; i < ndets; ++i) { | ||
| int ioff = i * row_stride; | ||
| int64_t ioff = i * row_stride; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ding |
||
|
|
||
| T* data_row = data + ioff; | ||
|
|
||
|
|
@@ -1153,7 +1153,7 @@ void _detrend(T* data, const int ndets, const int nsamps, const int row_stride, | |
| else if (method == "median") { | ||
| #pragma omp parallel for num_threads(nthreads) | ||
| for (int i = 0; i < ndets; ++i) { | ||
| int ioff = i * row_stride; | ||
| int64_t ioff = i * row_stride; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ding |
||
|
|
||
| T* data_row = data + ioff; | ||
|
|
||
|
|
@@ -1185,7 +1185,7 @@ void _detrend(T* data, const int ndets, const int nsamps, const int row_stride, | |
|
|
||
| #pragma omp parallel for num_threads(nthreads) | ||
| for (int i = 0; i < ndets; ++i) { | ||
| int ioff = i * row_stride; | ||
| int64_t ioff = i * row_stride; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ding |
||
|
|
||
| T* data_row = data + ioff; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import unittest | ||
|
|
||
| import so3g | ||
| import numpy as np | ||
|
|
||
|
|
||
| class TestOverflowBlock(unittest.TestCase): | ||
|
|
||
| def test_overflow(self): | ||
| a = np.zeros((4050, 603260), dtype='float32') | ||
| so3g.block_minmax(a, a, 800, 2, 0) | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a bunch of unit tests for the "large array limit" of all the array_ops functions? They could be disabled by default but it would be nice to run them, against this PR for example, or anytime we add new stuff. |
||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to just change this to
<int64_t>?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change
shapebelow to beint_64then than is fine. I had avoided doing that because we had wanted to proceed with the assumption that the shape of the array should be limited s.t it is alwaysintin each dimension. Hencesizestays anint(and thusndetandnsampstayint) butvshapeis allowed to beint64_tso that we can check it even if it is more than anint.