Global variables are generally speaking completely unnecessary, so let's not even go there - anything you can do using them, can be done by passing around a reference to a context object when new objects are constructed.
Since the operations are mutually independent, you'll want to parallelize them, so you have only three choices that will perform well: a class member variable, a thread-local static variable, or an automatic variable. The array is 400MB in size (10e3^2*4=100e6*4), so it simply won't work as an automatic variable - you'll usually run out of stack.
Thus:
class ProcessData {
public:
static constexpr int N = 10000;
using Matrix = std::array<std::array<int, N>, N>;
void update(Data &data) {
thread_local static Matrix matrix;
// ...
}
};
The downside is that depending on the C++ runtime implementation, the matrix may be allocated on startup of each and every thread, and you may not wish that to be the case when 400MB is at stake.
Thus, you might wish to allocate it only on demand:
// .h
class ProcessData {
public:
static constexpr int N = 10000;
using Matrix = std::array<std::array<int, N>, N>;
private:
thread_local static std::unique_ptr<Matrix> matrix;
public:
void update(Data &data) {
if (!matrix) matrix.reset(new Matrix);
//...
}
};
// .cpp
thread_local std::unique_ptr<ProcessData::Matrix> ProcessData::matrix;
The matrix will be deallocated whenever the thread ends (e.g. a worker thread in a thread pool), but can also be deallocated explicitly: matrix.reset();