• No results found

Accelerating classical MD for multi-core CPUs and GPUs

N/A
N/A
Protected

Academic year: 2021

Share "Accelerating classical MD for multi-core CPUs and GPUs"

Copied!
28
0
0

Loading.... (view fulltext now)

Full text

(1)

LAMMPS Users and Developers Workshop and Symposium, March 24th-28th 2014

Dr. Axel Kohlmeyer

Associate Dean for Scientific Computing

College of Science and Technology Temple University, Philadelphia

http://sites.google.com/site/akohlmey/

[email protected]

Accelerating classical MD

Accelerating classical MD

for multi-core CPUs and GPUs

(2)

2

Standard LAMMPS Parallelization

● MPI based (MPI emulator for serial execution) ● Uses domain decomposition with 1 domain

per MPI task (= processor). Each MPI task looks after the atoms in its domain

● Atoms move from MPI

task to MPI task as they move through the system

● Assumes same amount of

work (force computations) in each domain.

(3)

3

Why Bother Adding OpenMP?

1.Why not do it?

a) LAMMPS is already very parallel

b) Even more run-time settings to optimize

c) OpenMP is often less effective than MPI (for MD)

2. Why do it anyway?

a) On multi-core machines (Cray XT5) LAMMPS can run faster with MPI when some CPU cores are idle b) Parallelization over particles, not domains

c) PPPM has scaling limitations. At high node counts it would be better to run it only on a subset of tasks

(4)

4

OpenMP Parallelization

● OpenMP is directive based

=> well written code works with or without

● OpenMP can be added incrementally ● OpenMP only works in shared memory

=> multi-core processors are now ubiquitous

● OpenMP hides the calls to a threads library

=> less flexible, more overhead, but less effort

● Caution: need to worry about race conditions,

(5)

5

How to add OpenMP to LAMMPS

● LAMMPS is very modular, just add new classes

derived from non-threaded implementation

● Pairwise interactions (consume most time)

● i,j nested loop over neighbors can be parallelized ● each thread processes different “i” atoms

● Neighbor list build (binning still serial)

● i,j nested loop over atoms and neighboring bins

● Dihedrals and other bonded interactions

(6)

6

Threading Class Relations

PairLJ

- serial implementation - all non-threaded code PairLJOMP

- derived from PairLJ and ThrOMP

- replaces ::compute() with threaded version - gets access to ThrData instance from FixOMP

ThrOMP

- thread-safe utility functions - reduction of per-thread force ThrData

- per-thread accumulators - one instance per thread FixOMP

- regularly called during MD loop - determines when to reduce forces - manages ThrData instances

(7)

7

Naive OpenMP LJ Kernel

#if defined(_OPENMP) #pragma omp parallel for default(shared) \     private(i) reduction(+:epot) #endif     for(i=0; i < (sys­>natoms)­1; ++i) {         double rx1=sys­>rx[i];         double ry1=sys­>ry[i];         double rz1=sys­>rz[i];         [...] #if defined(_OPENMP) #pragma omp critical #endif       {       sys­>fx[i] += rx*ffac;       sys­>fy[i] += ry*ffac;       sys­>fz[i] += rz*ffac;       sys­>fx[j] ­= rx*ffac;       sys­>fy[j] ­= ry*ffac;       sys­>fz[j] ­= rz*ffac;       }        {       sys­>fx[i] += rx*ffac;       sys­>fy[i] += ry*ffac;       sys­>fz[i] += rz*ffac;       sys­>fx[j] ­= rx*ffac;       sys­>fy[j] ­= ry*ffac;       sys­>fz[j] ­= rz*ffac;       } Race condition:

“i” will be unique for each thread, but not “j” Or some “j” may be an “i” of another thread => multiple threads

update the same location

Each thread will work on different values of “i”

The “critical” directive will let only one thread execute this block at a time Timings (108 atoms): serial: 4.0s 1 thread: 4.2s 2 threads: 7.1s 4 threads: 7.7s 8 threads: 8.6s

(8)

8

Alternatives to “omp critical”

Use omp atomic to protect each force addition

=> requires hardware support (modern x86)

1Thr: 6.3s, 2Thr: 5.0s, 4Thr: 4.4s, 8Thr: 4.2s => faster than omp critical for multiple threads but it is slower than the serial code (4.0s)

● Don't use Newton's 3rd Law

=> no race condition

1Thr: 6.5s, 2Thr: 3.7s, 4Thr: 2.3s, 8Thr: 2.1s => better scaling, but 2 threads ~= serial speed => this is what is done on GPU (many threads)

(9)

9

“MPI-like” Approach with OpenMP

#if defined(_OPENMP) #pragma omp parallel reduction(+:epot) #endif     {  double *fx, *fy, *fz; #if defined(_OPENMP)         int tid=omp_get_thread_num(); #else         int tid=0; #endif         fx=sys­>fx + (tid*sys­>natoms); azzero(fx,sys­>natoms);         fy=sys­>fy + (tid*sys­>natoms); azzero(fy,sys­>natoms);         fz=sys­>fz + (tid*sys­>natoms); azzero(fz,sys­>natoms);         for(int i=0; i < (sys­>natoms ­1); i += sys­>nthreads) {       int ii = i + tid;       if (ii >= (sys­>natoms ­1)) break;       rx1=sys­>rx[ii];       ry1=sys­>ry[ii];       rz1=sys­>rz[ii];

Thread number is like MPI rank

sys->fx holds storage for one full fx array for each thread => race condition is avoided.

(10)

10

MPI-like Approach with OpenMP (2)

#if defined (_OPENMP) #pragma omp barrier #endif     i = 1 + (sys­>natoms / sys­>nthreads);     fromidx = tid * i;     toidx = fromidx + i;     if (toidx > sys­>natoms) toidx = sys­>natoms;     for (i=1; i < sys­>nthreads; ++i) {         int offs = i*sys­>natoms;         for (int j=fromidx; j < toidx; ++j) {       sys­>fx[j] += sys­>fx[offs+j];       sys­>fy[j] += sys­>fy[offs+j];       sys­>fz[j] += sys­>fz[offs+j];         }     }

● We need to write our own reduction:

Need to make certain, all threads are done with computing forces

Use threads to parallelize the reductions

(11)

11

OpenMP Timings Comparison

omp critical timings

1Thr: 4.2s, 2Thr: 7.1s, 4Thr: 7.7s, 8Thr: 8.6s

omp atomic timings

1Thr: 6.3s, 2Thr: 5.0s, 4Thr: 4.4s, 8Thr: 4.2s

omp parallel region (MPI-like) timings

1Thr: 4.0s, 2Thr: 2.5s, 4Thr: 2.2s, 8Thr: 2.5s

● No Newton's 3rd law timings

1Thr: 6.5s, 2Thr: 3.7s, 4Thr: 2.3s, 8Thr: 2.1s

=> the omp parallel variant is best for few threads, no Newton's 3rd variant better for more threads

(12)

12 1 2 3 4 6 8 12 16 20 24 32 0 5 10 15 20

2x Intel Xeon 2.66Ghz (Harpertown) w/ DDR Infiniband

CHARMM (lj/charmm/coul/long + pppm), 32000 Atoms

Number of Nodes T im e fo r 10 00 M D s te ps /s 1 6 11 16 21 26 31 0% 10% 20% 30% 40% 50% 60% 70% 80% Number of Nodes P ar a lle l E ffi ci en cy 8 MPI / Node

4 MPI + 2 OpenMP / Node 4 MPI / Node

2 MPI + 4 OpenMP / Node 1 MPI + 8 OpenMP / Node

(13)
(14)

14

Running Big

● Vesicle fusion study:

impact of lipid ratio in binary mixture

● cg/cmm/coul/long ● Experimental size

=> 4M CG-beads for 1 vesicle and solvent

● 30,000,000 CPU hour

(15)

15

Strong Scaling (Cray XT5)

27 63 148 345 805 1878

0.04 0.08 0.17 0.36

1 Vesicle CG System / 3,862,854 CG-Beads

12 MPI / 1 OpenMP 6 MPI / 2 OpenMP 4 MPI / 3 OpenMP 2 MPI / 6 OpenMP # Nodes Ti m e pe r M D s te p (s ec )

(16)

16

Strong Scaling (2) (Cray XT5)

256 569 1263 2805 6231 0.1 0.15 0.24 0.39 0.61

8 Vesicles CG-System / 30,902,832 CG-Beads

12 MPI / 1 OpenMP 6 MPI / 2 OpenMP 4 MPI / 3 OpenMP 2 MPI / 6 OpenMP # Nodes Ti m e pe r M D S te p (s ec )

(17)

17 128 256 384 768 128 256 384 768 768 0 5 10 15 20 25

Rhodopsin Benchmark, 860k Atoms, 64 Nodes, Cray XT5

Other Neighbor Comm Kspace Bond Pair # PE Ti m e in s ec on ds

The Curse of the k-Space (1)

4 M P I/ N od e 6 M P I/ N od e 1 2 M P I/ N o de 2 M P I + 6 O pe n M P /N o de 1 MPI/Node + OpenMP

(18)

18

The Curse of the k-Space (2)

256 512 768 1536 256 512 768 1536 1536 0 5 10 15 20 25

Rhodopsin Benchmark, 860k Atoms, 128 Nodes, Cray XT5

Other Neighbor Comm Kspace Bond Pair # PE Ti m e in s ec on ds 4 M P I/ N od e 6 M P I/ N od e 1 2 M P I/ N o de 2 M P I + 6 O pe n M P /N o de 1 MPI/Node + OpenMP

(19)

19

The Curse of the k-Space (3)

1024 2048 3072 6144 1024 2048 3072 6144 6144 0 5 10 15 20 25

Rhodopsin Benchmark, 860k Atoms, 512 Nodes, Cray XT5

Other Neighbor Comm Kspace Bond Pair # PE T im e i n s e c o n d s 4 M P I/ N o de 6 M P I/ N od e 12 M P I/ N od e 2 M P I + 6 O pe n M P /N o de 1 MPI/Node + OpenMP

(20)

20

Additional Improvements

● OpenMP threading added to charge density

accumulation and force application in PPPM

● Force reduction only done on last /omp style

● Integration style verlet/split contributed by Voth

group which run k-space on separate partition (compatible with OpenMP version of PPPM)

● Added threading to selected fixes like charge

equilibration for COMB many-body potential

(21)

21

Current GPU Support in LAMMPS

● Multiple developments from different groups

● Converged to two efforts with two philosophies ● GPU package (minimalistic)

● pair styles, neighbor lists and k-space (optional): ● Download coordinates, retrieve forces

● Run asynchronously to bonded (and k-space)

● USER-CUDA package (see next talk)

● Replace all classes that touch atom data

(22)

22

Special Features of “GPU” Package

● Can be compiled for CUDA or OpenCL due to

using “Geryon” preprocessor macros

● Can attach multiple MPI tasks to one GPU for

improved GPU utilization (up to 4x

over-subscription on “Fermi”, up to 15x on “Kepler”)

● Uses a “fix” to manage GPUs and compute

kernel dispatch, “styles” dispatch kernels

asynchronously, “fix” then retrieves the forces after all other force computations are completed

(23)

23

1x GPU Performance in LAMMPS

8 Core, 2.8GHz GTX 480 sp GTX 480 mp GTX 480 dp C2050 sp C2050 mp C2050 dp ATI V8800 sp ATI V8800 mp ATI V8800 dp

0 20 40 60 80 100 120 140

Bulk Water, LJ+long-range electrostatics

PPPM on GPU 5,376 Water 5000 Step 21,504 Water 1000 Step Ti m e in s e co n d s GeForce Tesla FirePro

(24)

24

Multiple GPUs per Node

8 Cores, 2.8GHz 1x C2050 mp 2x C2050 mp 4x C2050 mp 1x V8800 mp 2x V8800 mp 4x V8800 mp 0 10 20 30 40 50 60 70 80 90 100

Bulk Water, LJ + long-range electrostatics

PPPM on GPU 5,376 water, 5000 steps 21,504 water, 1000 steps Ti m e in s e co n d s Tesla FirePro

(25)

25

Comments on GPU Acceleration

● Mixed precision (force computation in single,

force accumulation in double precision) good compromise: little overhead, good accuracy on forces, stress/pressure less so

● GPU acceleration larger for models that require

more computation in force kernel

● Acceleration drops with lower number of atoms

per GPU => limited strong scaling on “big iron”

(26)

26

Installation of USER-OMP and GPU

● USER-OMP package:

● make yes-user-omp to install sources

● Add -fopenmp (GNU) or -openmp (Intel) to CC and

LINK definitions in your makefile to enable OpenMP

● Compilation without OpenMP => similar to OPT

● GPU package:

● Compile library in lib/gpu for CUDA or OpenCL ● make yes-gpu to install style sources which are

wrappers for GPU library

(27)

27

Using Accelerated Code

● All accelerated styles are optional and need to

be activated in the input or from command line

● Naming convention lj/cut -> lj/cut/omp lj/cut/gpu ● From command line -sf omp or -sf gpu

● Inside script: suffix omp or suffix gpu

and suffix on or suffix off

● Use package omp/gpu command to adjust

settings for acceleration and selection of GPUs

(28)

28

Conclusions and Outlook: OpenMP

● OpenMP+MPI is almost always a win, especially

with large node counts (=> capability computing)

● USER-OMP also contains serial optimizations

and thus useful without OpenMP compiled in

● Minimal changes to LAMMPS core code

● USER-OMP only a transitional implementation

since efficient only on a small number of threads

● Longer-term solution also needs to consider

vectorization and thus be more GPU-like and

References

Related documents