View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.potential.nonbonded;
39  
40  import edu.rit.pj.IntegerSchedule;
41  import edu.rit.util.Range;
42  import java.util.logging.Logger;
43  
44  /**
45   * A fixed schedule that balances pairwise work across threads.
46   *
47   * @author Michael J. Schnieders
48   * @since 1.0
49   */
50  public class PairwiseSchedule extends IntegerSchedule {
51  
52    private static final Logger logger = Logger.getLogger(PairwiseSchedule.class.getName());
53    private final int nThreads;
54    private final Range[] ranges;
55    private final boolean[] threadDone;
56    private int nAtoms;
57    private int threadOffset;
58  
59    /**
60     * Constructor for PairwiseSchedule.
61     *
62     * @param nThreads a int.
63     * @param nAtoms a int.
64     * @param ranges an array of {@link edu.rit.util.Range} objects.
65     */
66    public PairwiseSchedule(int nThreads, int nAtoms, Range[] ranges) {
67      this.nAtoms = nAtoms;
68      this.nThreads = nThreads;
69      threadOffset = 0;
70      this.ranges = ranges;
71      threadDone = new boolean[nThreads];
72    }
73  
74    /**
75     * {@inheritDoc}
76     *
77     * <p>This is a fixed schedule.
78     */
79    @Override
80    public boolean isFixedSchedule() {
81      return true;
82    }
83  
84    /** {@inheritDoc} */
85    @Override
86    public Range next(int threadID) {
87      if (!threadDone[threadID]) {
88        threadDone[threadID] = true;
89        return ranges[threadID];
90      }
91      return null;
92    }
93  
94    /**
95     * setAtoms.
96     *
97     * @param nAtoms a int.
98     */
99    public void setAtoms(int nAtoms) {
100     this.nAtoms = nAtoms;
101   }
102 
103   /** {@inheritDoc} */
104   @Override
105   public void start(int nThreads, Range chunkRange) {
106     assert (nThreads == this.nThreads);
107     assert (chunkRange.lb() == 0);
108     assert (chunkRange.ub() == nAtoms - 1);
109 
110     for (int i = 0; i < nThreads; i++) {
111       threadDone[i] = false;
112     }
113   }
114 
115   /**
116    * updateRanges
117    *
118    * @param totalInteractions a int.
119    * @param atomsWithInteractions the number of chunks of interactions.
120    * @param listCount an array of int.
121    */
122   void updateRanges(int totalInteractions, int atomsWithInteractions, int[] listCount) {
123     int id = 0;
124     int goal = totalInteractions / (nThreads + threadOffset);
125     int num = 0;
126     int start = 0;
127     for (int i = 0; i < nAtoms; i++) {
128       num += listCount[i];
129       if (num >= goal) {
130 
131         // Last thread gets the remaining atoms.
132         if (id == nThreads - 1) {
133           ranges[id] = new Range(start, nAtoms - 1);
134           break;
135         }
136 
137         ranges[id] = new Range(start, i);
138 
139         // Zero out the interaction counter.
140         num = 0;
141         // Next thread.
142         id++;
143         // Next range starts at i+1.
144         start = i + 1;
145 
146         // Out of atoms. Threads remaining get a null range.
147         if (start == nAtoms) {
148           if (atomsWithInteractions > nThreads + threadOffset + 1) {
149             threadOffset++;
150             updateRanges(totalInteractions, atomsWithInteractions, listCount);
151             break;
152           }
153           for (int j = id; j < nThreads; j++) {
154             ranges[j] = null;
155           }
156           break;
157         }
158       } else if (i == nAtoms - 1) {
159 
160         // Last atom without reaching goal for current thread.
161         if (id < nThreads - 1 && atomsWithInteractions > nThreads + threadOffset + 1) {
162           threadOffset++;
163           updateRanges(totalInteractions, atomsWithInteractions, listCount);
164           break;
165         }
166         ranges[id] = new Range(start, nAtoms - 1);
167         for (int j = id + 1; j < nThreads; j++) {
168           ranges[j] = null;
169         }
170       }
171     }
172     threadOffset = 0;
173   }
174 }