Recent notes
What's it like to be in geophysics?
January 26, 2008
Dan Shannon is a student-athlete at Grandview Heights High School in Columbus, Ohio. Dan recently asked me some thought-provoking questions:
What do you want your students to get the most out of what you teach (concerning geophysics)?
Most of our students enjoy thinking analytically; they think physics, math, and computer science are fun. I want them to learn how to extend and apply what they already enjoy to design and implement new technology for geophysical exploration, which can be even more fun. In other words, I want my students to develop skills that will enable them to enjoy their work so much that it becomes play, something they might do for only room and board; but they won't because their skills are both rare and valuable.
How do you believe the continued study of geophysics affects the world?
Geophysics enables us to see and better understand the earth's interior. Our ability to do this has many applications. Some geophysicists explore for resources (oil, gas, water, minerals, ...), unexploded ordinance, aging infrastructure in urban areas, ancient civilizations, sites for nuclear waste and CO2 sequestration, and so on. Other geophysicists look much deeper and try to understand geologic processes and forces that cause earthquakes. Or they might use seismic waves generated by earthquakes to better image the earth's core and mantle. This list is far from complete. I should at least mention other planets, and similarities between geophysical and medical imaging. But these are some of the applications of geophysics that have worldwide importance.
What are the unique aspects of geophysical engineering?
The applications described above are rather unique. And perhaps the difference between science and engineering is less well-defined in geophysics. But beyond that, geophysical engineering is much like other engineering fields. For example, I used to think that geophysicists have more opportunities to travel abroad, to see the world. But I have learned by talking with Mines graduates in other engineering fields that many have such opportunities today.
How do the working conditions compare to other jobs; are they indoors, outdoors, both?
Geophysicists work both indoors and/or outdoors. In my geophysical career, I have worked outside covered in drilling mud and inside programming some of the world's fastest supercomputers. Never at the same time, of course, and more of the latter.
What skills can/need to be integrated with geophysical engineering in order to be successful?
In addition to geology and physics (clearly!), successful geophysicists are likely to be skilled in mathematics, computer science, and to a lesser extent chemistry. When I ask my colleagues what subject they wish they had studied more while in school, most of them say math, because that one seems to be most difficult to pick up on the job while solving geophysical problems.
How interpersonal is the study of geophysics?
Probably no more or less so than any other scientific or engineering discipline. But few geophysicists work alone, and many today work in teams with other geoscientists and engineers.
What opportunities does geophysical engineering offer, while in school, that other areas of study do not offer?
The opportunity to learn how mathematics, physics, computer science and geology can all be woven together to do amazing things. Our students tend to be those who enjoy putting these subjects together. Opportunities to work both outdoors, acquiring geophysical data, and indoors, developing and using computer software that analyzes those data, may also be unusual. An example of this is our four-week summer field session, which our students seem to especially enjoy, relative to other students at Mines.
What compels you to be involved in geophysics?
I am more compelled to design and build computer programs, software machines that can be wonderful combinations of art and engineering. Geophysics just happens to provide some of the most challenging computational problems and opportunities. With that interest in computing and an education in physics, I more or less stumbled into geophysics.
What does an ordinary day of work involve?
This varies quite a lot from day to day, but typically includes one or more of the following activities: preparing and teaching classes, working with students, working with colleagues, analytical work for research, writing computer software, writing prose, responding to email, and so on.
What does an extraordinary day of work involve?
A breakthrough in any of the activities listed above followed by a workout with the Mines varsity swimming team with some favorite music running in my brain. So what is a breakthrough? For me that could be working with a student to find a simple and elegant solution to an analytical or computational problem. Or perhaps it is when I am stuck with a programming error while lecturing in a computer science class, and everyone becomes very still (because this rarely happens), and then a student finds the error before I do. Such days are extraordinary.
Tiny displacements in time-lapse seismic images
January 24, 2007
In time-lapse seismic imaging, we often observe displacements of features in images recorded at different times. After accounting for changes in data acquisition, these displacements can be related to compaction of reservoir rocks as fluids are produced from them. We call these displacements apparent shifts because they may be more directly related to changes in seismic wave velocity outside the reservoir than to physical movements of reservoir boundaries.
- One of the two seismic images we cross-correlated to detect tiny displacement vectors, one for each image sample.
Today, we typically measure only vertical apparent shifts, for two reasons. First, the force of gravity leads us to expect vertical shifts to be larger than horizontal shifts. Second, it is easier to measure shifts perpendicular to image features than to measure shifts parallel to those features.
The second problem is illustrated in the figure below, which shows 2-D cross-correlations of local Gaussian windows of two seismic images. The correlation peaks are well resolved vertically, but poorly resolved horizontally. Because the locations of the peaks correspond to the apparent shifts we seek to estimate, horizontal components of those shifts are poorly resolved.
- Local cross-correlations (normalized). This is is a small subset of the correlations that we compute for every image sample. Note the small vertical shifts of some correlation peaks. Horizontal shifts are more difficult to see.
We say "vertical" and "horizontal", when what we really mean is "perpendicular" and "parallel" to features in our images. If those features were dipping at an angle of 45 degrees, then resolution would be equally poor in both horizontal and vertical directions.
Ideally the peaks of our cross-correlations would be isotropic, with roughly the same resolution in all directions, as in the figure below. The processing used here is an example of adapting techniques from general image processing to solve specific problems in seismic imaging. Here we computed so-called phase correlations, and our adaptation is to do this in a seamless way for every sample in our images.
- Local phase correlations (normalized). Again, a small subset of the correlations that we compute for every image sample. Both vertical and horizontal components of shifts can be accurately estimated from the locations of peaks of these phase correlations.
Using phase correlations, we can reliably estimate both vertical and horizontal shifts in time-lapse seismic images with sub-pixel precision. In one example, we have used phase correlations to observe horizontal apparent shifts of about five meters in 3-D images sampled with twenty-five meter trace spacings; and these small sub-sample shifts are correlated with the geometry of the target reservoir.
Our problem now is to analyze these apparent shift vectors, to better understand how they are related to changes within and above producing reservoirs.
Parallel loops with atomic integers
July 29, 2006
A computer you buy today is likely to have multiple cores. A "core" is a CPU that may coexist with other CPUs within a single microprocessor. For example, if you have a dual-processor system with dual-core processors, then you really have a quad-core system, one with essentially four CPUs.
Systems like these are becoming commonplace, because CPUs are not getting faster as they once did. Instead, we are getting more CPUs in a single package.
To take advantage of multi-core computers, we might simply run multiple applications simultaneously. But this solution may be impractical. Sometimes we need a single software application to run faster. In this case, we need to get multiple processors working simultaneously on the same problem within a single application.
Our current situation is summarized well by Herb Sutter, in The Free Lunch is Over: A Fundamental Turn Toward Concurrency in Software (2005, Dr. Dobb's Journal, v. 30, n. 3).
An example
Scientific computing often has outer loops with iterations
that can be performed independently and concurrently.
For example, when computing a matrix product C = A×B, we might
compute each column of the matrix C independently.
Here is some Java code that computes the j'th column of C:
static void computeColumn(
int j, float[][] a, float[][] b, float[][] c)
{
int ni = c.length;
int nk = b.length;
for (int i=0; i<ni; ++i) {
float cij = 0.0f;
for (int k=0; k<nk; ++k)
cij += a[i][k]*b[k][j];
c[i][j] = cij;
}
}
We usually optimize this code by mixing and unrolling these loops, but those optimizations are not relevant here.
To compute the matrix product C, we need only an outer loop over its columns:
int nj = c[0].length;
for (int j=0; j<nj; ++j)
computeColumn(j,a,b,c);
The problem with this single-threaded program is that it will not run any faster on a quad-core system than it would on a single-core system. Three CPUs may be idle while one does all the work.
Multi-threading
To use all four cores concurrently in a single program, we need multiple threads. We could write the outer loop like this:
int nthread = 4;
final int nj = c[0].length;
Thread[] threads = new Thread[nthread];
for (int ithread=0; ithread<nthread; ++ithread) {
threads[ithread] = new Thread(new Runnable() {
public void run() {
for (int j=0; j<nj; ++j)
computeColumn(j,a,b,c);
}
});
}
startAndJoin(threads);
The last statement calls a utility method that simply starts and
then joins all of the threads in the specified array of threads.
This is easy enough with Java's standard classes
Thread and Runnable.
But this multi-threaded program is no faster!
Each thread maintains it's own loop index j
and will simply duplicate the work of the other three threads.
All four cores will be busy (good) doing the same work
(bad).
Chunky multi-threading
We want different threads to compute different columns. But which columns do we assign to each thread? We could simply divide our outer loop into four chunks, so that each of the four threads computes one fourth of the columns:
int nthread = 4;
int nj = c[0].length;
int mj = 1+nj/nthread;
Thread[] threads = new Thread[nthread];
for (int ithread=0; ithread<nthread; ++ithread) {
final int jfirst = ithread*mj;
final int jlast = min(jfirst+mj,nj);
threads[ithread] = new Thread(new Runnable() {
public void run() {
for (int j=jfirst; j<jlast; ++j)
computeColumn(j,a,b,c);
}
});
}
startAndJoin(threads);
This program is better, but is efficient only when all four threads get equal access to the four CPUs. That seldom happens. Threads that finish computing their chunk of columns simply stop working. They do not help other threads complete their chunks. (Have you ever worked with a group like this?) This program is only as fast as its slowest thread.
An atomic outer loop index
A more efficient solution is to have all four threads keep working
until all columns have been computed.
(No one stops working until the job is done.)
Let's have each thread compute the next column not already computed
or being computed.
We do that by letting all four threads share a single outer loop index,
using the standard Java class AtomicInteger:
int nthread = 4;
final int nj = c[0].length;
final AtomicInteger aj = new AtomicInteger();
Thread[] threads = new Thread[nthread];
for (int ithread=0; ithread<nthread; ++ithread) {
threads[ithread] = new Thread(new Runnable() {
public void run() {
for (int j=aj.getAndIncrement(); j<nj;
j=aj.getAndIncrement())
computeColumn(j,a,b,c);
}
});
}
startAndJoin(threads);
The AtomicInteger aj holds the shared outer loop index
that all threads get and increment.
The name AtomicInteger implies that this
get-and-increment is an indivisible atomic operation,
one that cannot be interrupted or corrupted by another thread
doing the same thing.
With this program, our four threads need not perform an equal amount of work, and all threads continue to run until all of the columns are computed. On an otherwise quiet quad-core system, this program runs approximately four times faster than the single-threaded version.
Moreover, on a single-core system this program is almost as fast
as the single-threaded version.
For large matrices, the extra computation required to launch multiple
threads and get-and-increment an AtomicInteger is negligible.
For small matrices, we might apply the same technique to some other more
outer loop.