C++ (Qt) for(uint_type steps = 0; !tol(radius, steps); ++steps) { mean_x = x; for (uint_type i = 0; i < point_per_step; ++i) { std::uniform_real_distribution<real_type> dist(mean_x - radius, mean_x + radius); vector_type c = dist(rng); real_type cur_val = function(cx); if (cur_val < min) { x = std::move(cx); min = cur_val; } } dx = x - mean_x; real_type sqr_ds = dx*dx; /* ds^2 = (dx, dx) */ if (sqr_ds < radius*radius*mean_sqr_radius) radius *= m_params.alpha; else radius = std::min(m_params.init_radius, radius*m_params.beta); observer(x, min, steps); }
C++ (Qt)#include <iostream> #include "minsearch.h"#include "model_energy.h"#include "potential.h" static constexpr unsigned int NAtomsA = 50; // Number of atoms type Astatic constexpr unsigned int NAtomsB = 50; // Number of atoms type Bstatic constexpr unsigned int NAtoms = NAtomsA + NAtomsB; // Total number of atomsstatic constexpr unsigned int Dim = 2; // Physical dimension int main(){ ABModelEnergy<double, NAtomsA, NAtomsB> modelEnergy(std::bind(potential, std::placeholders::_1, 1.0, -10.0, 1.0), std::bind(potential, std::placeholders::_1, 1.0, -12.0, 1.0), std::bind(potential, std::placeholders::_1, 0.0, -20.0, 4.0)); std::vector<double> x(Dim*NAtoms, 0.0); // The initial phase vector (all atoms are in the zero point now) double init_radius = 0.1; unsigned int point_per_step = 8*10; double alpha = 0.9; double beta = 2.0; //thread pool realisation specmath::minsearch<double> minsearch(init_radius, point_per_step, alpha, beta); auto start = std::chrono::high_resolution_clock::now(); const double eps = 1e-6; const unsigned long max_steps = 3000000000; double res = minsearch.find_minimum(modelEnergy, x, specmath::breaker<double>(eps, max_steps)); std::cout << " (multi threads) Energy = " << res << std::endl; auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop-start).count(); std::cout << "duration = " << duration << " sec" << std::endl; // single thread realisation specmath::minsearch_st<double> minsearch_st(init_radius, point_per_step, alpha, beta); for (auto & xi : x) xi = 0.0; start = std::chrono::high_resolution_clock::now(); res = minsearch_st.find_minimum(modelEnergy, x, specmath::breaker<double>(eps, max_steps)); std::cout << "(single threads) Energy = " << res << std::endl; stop = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast<std::chrono::seconds>(stop-start).count(); std::cout << "duration = " << duration << " sec" << std::endl; return 0;}
C++ (Qt)for(uint_type steps = 0; !tol(radius, steps); ++steps) { mean_x = x; std::atomic_int ntests(m_params.point_per_step); for (uint_type i = 0; i < m_num_threads; ++i) results[i] = pool.add_task(std::bind(task, radius, std::ref(ntests))); for (auto & res : results) res.wait(); ...
C++ (Qt)auto task = [&](const real_type & r, std::atomic_int & ntests) { static thread_local std::random_device rd; static thread_local rng_type rng(rd()); static thread_local std::uniform_real_distribution<real_type> dist; typedef typename std::uniform_real_distribution<real_type>::param_type range_t; // ntests - это и есть атомарный счётчик point_per_step while (std::atomic_fetch_sub(&ntests, 1) > 0) { vector_type cx = mean_x; std::transform(mean_x.begin(), mean_x.end(), cx.begin(), [&](const real_type & x0){ return dist(rng, range_t(x0-r, x0+r)); }); real_type cur_val = function(cx); std::lock_guard<std::mutex> locker(mutex); if (cur_val < min) { x = std::move(cx); min = cur_val; } } };
C++ (Qt) ... real_type cur_val = function(cx); if (cur_val < min) { std::lock_guard<std::mutex> locker(mutex); if (cur_val < min) { x = std::move(cx); min = cur_val; } }