Grid 0.7.0
ScalarInteractionAction.h
Go to the documentation of this file.
1/*************************************************************************************
2
3 Grid physics library, www.github.com/paboyle/Grid
4
5 Source file: ./lib/qcd/action/gauge/WilsonGaugeAction.h
6
7 Copyright (C) 2015
8
9 Author: Guido Cossu <guido,cossu@ed.ac.uk>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License along
22 with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25 See the full license in the file "LICENSE" in the top level distribution
26directory
27 *************************************************************************************/
28/* END LEGAL */
29
30#pragma once
31
32// Note: this action can completely absorb the ScalarAction for real float fields
33// use the scalarObjs to generalise the structure
34
36
37template <class Impl, int Ndim>
38class ScalarInteractionAction : public Action<typename Impl::Field>
39{
40public:
42
43private:
47 const unsigned int N = Impl::Group::Dimension;
48
49 typedef typename Field::vector_object vobj;
51
53 int npoint = 2 * Ndim;
54 std::vector<int> directions; //
55 std::vector<int> displacements; //
56
57public:
58 ScalarInteractionAction(RealD ms, RealD l, RealD gval) : mass_square(ms), lambda(l), g(gval), displacements(2 * Ndim, 0), directions(2 * Ndim, 0)
59 {
60 for (int mu = 0; mu < Ndim; mu++)
61 {
62 directions[mu] = mu;
63 directions[mu + Ndim] = mu;
64 displacements[mu] = 1;
65 displacements[mu + Ndim] = -1;
66 }
67 }
68
69 virtual std::string LogParameters()
70 {
71 std::stringstream sstream;
72 sstream << GridLogMessage << "[ScalarAction] lambda : " << lambda << std::endl;
73 sstream << GridLogMessage << "[ScalarAction] mass_square : " << mass_square << std::endl;
74 sstream << GridLogMessage << "[ScalarAction] g : " << g << std::endl;
75 return sstream.str();
76 }
77
78 virtual std::string action_name() { return "ScalarAction"; }
79
80 virtual void refresh(const Field &U, GridSerialRNG & sRNG, GridParallelRNG &pRNG) {}
81
82 virtual RealD S(const Field &p)
83 {
84 assert(p.Grid()->Nd() == Ndim);
85 static Stencil phiStencil(p.Grid(), npoint, 0, directions, displacements);
86 phiStencil.HaloExchange(p, compressor);
87 Field action(p.Grid()), pshift(p.Grid()), phisquared(p.Grid());
88 phisquared = p * p;
89 action = (2.0 * Ndim + mass_square) * phisquared - lambda * phisquared * phisquared;
90
91
92 autoView( p_v , p, CpuRead);
93 autoView( action_v , action, CpuWrite);
94 for (int mu = 0; mu < Ndim; mu++)
95 {
96 // pshift = Cshift(p, mu, +1); // not efficient, implement with stencils
97 thread_for(i, p.Grid()->oSites(),
98 {
99 int permute_type;
100 StencilEntry *SE;
101 vobj temp2;
102 const vobj *temp, *t_p;
103
104 SE = phiStencil.GetEntry(permute_type, mu, i);
105 t_p = &p_v[i];
106 if (SE->_is_local)
107 {
108 temp = &p_v[SE->_offset];
109 if (SE->_permute) {
110 permute(temp2, *temp, permute_type);
111 action_v[i] -= temp2 * (*t_p) + (*t_p) * temp2;
112 } else {
113 action_v[i] -= (*temp) * (*t_p) + (*t_p) * (*temp);
114 }
115 }
116 else
117 {
118 action_v[i] -= phiStencil.CommBuf()[SE->_offset] * (*t_p) + (*t_p) * phiStencil.CommBuf()[SE->_offset];
119 }
120 });
121 // action -= pshift*p + p*pshift;
122 }
123 // NB the trace in the algebra is normalised to 1/2
124 // minus sign coming from the antihermitian fields
125 return -(TensorRemove(sum(trace(action)))).real() * N / g;
126 };
127
128 virtual void deriv(const Field &p, Field &force)
129 {
130 double t0 = usecond();
131 assert(p.Grid()->Nd() == Ndim);
132 force = (2. * Ndim + mass_square) * p - 2. * lambda * p * p * p;
133 double interm_t = usecond();
134
135 // move this outside
136 static Stencil phiStencil(p.Grid(), npoint, 0, directions, displacements);
137
138 phiStencil.HaloExchange(p, compressor);
139 double halo_t = usecond();
140 // int chunk = 128;
141 //for (int mu = 0; mu < Nd; mu++) force -= Cshift(p, mu, -1) + Cshift(p, mu, 1);
142
143 // inverting the order of the loops slows down the code(! g++ 7)
144 // cannot try to reduce the number of force writes by factor npoint...
145 // use cache blocking
146 for (int point = 0; point < npoint; point++)
147 {
148
149 autoView( p_v , p, CpuRead);
150 autoView( force_v , force, CpuWrite);
151
152 int permute_type;
153 StencilEntry *SE;
154 const vobj *temp;
155
156 thread_for(i, p.Grid()->oSites(),
157 {
158 SE = phiStencil.GetEntry(permute_type, point, i);
159 // prefetch next p?
160
161 if (SE->_is_local) {
162 temp = &p_v[SE->_offset];
163
164 if (SE->_permute) {
165 vobj temp2;
166 permute(temp2, *temp, permute_type);
167 force_v[i] -= temp2;
168 } else {
169 force_v[i] -= *temp; // slow part. Dominated by this read/write (BW)
170 }
171 } else {
172 force_v[i] -= phiStencil.CommBuf()[SE->_offset];
173 }
174 });
175 }
176 force *= N / g;
177
178 double t1 = usecond();
179 double total_time = (t1 - t0) / 1e6;
180 double interm_time = (interm_t - t0) / 1e6;
181 double halo_time = (halo_t - interm_t) / 1e6;
182 double stencil_time = (t1 - halo_t) / 1e6;
183 std::cout << GridLogIntegrator << "Total time for force computation (s) : " << total_time << std::endl;
184 std::cout << GridLogIntegrator << "Intermediate time for force computation (s): " << interm_time << std::endl;
185 std::cout << GridLogIntegrator << "Halo time in force computation (s) : " << halo_time << std::endl;
186 std::cout << GridLogIntegrator << "Stencil time in force computation (s) : " << stencil_time << std::endl;
187 double flops = p.Grid()->gSites() * (14 * N * N * N + 18 * N * N + 2);
188 double flops_no_stencil = p.Grid()->gSites() * (14 * N * N * N + 6 * N * N + 2);
189 double Gflops = flops / (total_time * 1e9);
190 double Gflops_no_stencil = flops_no_stencil / (interm_time * 1e9);
191 std::cout << GridLogIntegrator << "Flops: " << flops << " - Gflop/s : " << Gflops << std::endl;
192 std::cout << GridLogIntegrator << "Flops NS: " << flops_no_stencil << " - Gflop/s NS: " << Gflops_no_stencil << std::endl;
193 }
194};
195
197
198
accelerator_inline Grid_simd2< S, V > trace(const Grid_simd2< S, V > &arg)
Lattice< vobj > real(const Lattice< vobj > &lhs)
vobj::scalar_object sum(const vobj *arg, Integer osites)
#define autoView(l_v, l, mode)
GridLogger GridLogIntegrator(1, "Integrator", GridLogColours, "BLUE")
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
@ CpuRead
@ CpuWrite
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
double RealD
Definition Simd.h:61
SimpleCompressorGather< vobj, FaceGatherSimple > SimpleCompressor
accelerator_inline std::enable_if<!isGridTensor< T >::value, T >::type TensorRemove(T arg)
#define thread_for(i, num,...)
Definition Threads.h:60
double usecond(void)
Definition Timer.h:50
static INTERNAL_PRECISION U
Definition Zolotarev.cc:230
Base class for all actions.
Definition ActionBase.h:64
void HaloExchange(const Lattice< vobj > &source, compressor &compress)
Definition Stencil.h:610
ScalarInteractionAction(RealD ms, RealD l, RealD gval)
virtual std::string LogParameters()
Print the parameters of the action.
virtual void refresh(const Field &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG)
virtual void deriv(const Field &p, Field &force)
virtual RealD S(const Field &p)
virtual std::string action_name()
Report the name of the action.