QtCreator with MinGW : How to make compiler optimization - optimization

I am using QtCreator on windows, and I would like to know how to make my compiler optimize the output.
My understanding is that MinGW is a port of GCC. So, I should be able to use arguments such as -O2. However, in the "Projects" bar, the only things I see are :
Build step for qmake (probably not here, qmake is about the .pro files / MOC / Qt stuff ...)
Build step for mingw32-make (probably)
Clean steps (probably not)
So, I tried to add -O2 in the "Make arguments" box, but unfortunately, I get an error "invalid option --O"
For anyone interested, I was trying to make an implementation of the Ackermann function because I read that :
The Ackermann function, due to its definition in terms of extremely
deep recursion, can be used as a benchmark of a compiler's ability to
optimize recursion
The code (which doesn't really use Qt) :
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <ctime>
using namespace std;
int nbRecursion;
int nbRecursions9;
int Ackermann(int m, int n){
nbRecursion++;
if(nbRecursion % 1000000 == 0){
qDebug() << nbRecursions9 << nbRecursion;
}
if(nbRecursion == 1000000000){
nbRecursion = 0;
nbRecursions9++;
}
if(m==0){
return n+1;
}
if(m>0 && n>0){
return Ackermann(m-1,Ackermann(m, n-1));
}
if(m>0 && n==0){
return Ackermann(m-1,1);
}
qDebug() << "Bug at " << m << ", " << n;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
nbRecursion = 0;
nbRecursions9 = 0;
int m = 3;
int n = 13;
clock_t begin = clock();
Ackermann(m,n);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
qDebug() << "There are " << CLOCKS_PER_SEC << " CLOCKS_PER_SEC";
qDebug() << "There were " << nbRecursions9 << nbRecursion << " recursions in " << elapsed_secs << " seconds";
double timeX = 1000000000.0*((elapsed_secs)/(double)nbRecursion);
if(nbRecursions9>0){
timeX += elapsed_secs/(double)nbRecursions9;
}
qDebug() << "Time for a function call : " << timeX << " nanoseconds";
return a.exec();
}

-O2 is used by default when you do a release build. Only debug builds don't use optimization. Regardless, if you want to use specific compiler options, you do so in the project file (*.pro) itself, by appending your options to the QMAKE_CFLAGS_RELEASE (for C files) and QMAKE_CXXFLAGS_RELEASE (for C++ files). For example:
QMAKE_CFLAGS_RELEASE += -O3 -march=i686 -mtune=generic -fomit-frame-pointer
QMAKE_CXXFLAGS_RELEASE += -O3 -march=i686 -mtune=generic -fomit-frame-pointer
If you really want to use some specific options always, regardless of whether it's a debug or release build, then append to QMAKE_CFLAGS and QMAKE_CXXFLAGS instead. But usually, you'll only want optimization options in your release builds, not the debug ones.

Related

what brings about a dependency on tbb?

Using g++12 and CMake.
I have a source file
holes5.cpp
which does not
#include <execution>
and does not need to link to tbb.
Now if I add
#include <execution>
it does not require linking to tbb either. So what exact step does it take to start depending on tbb (thus requiring linking to tbb). I am confused.
Installed tbb via
sudo apt install libtbb-dev
In CMakeList.txt:
list(APPEND CMAKE_MODULE_PATH "deps/tbb/cmake/")
find_package(TBB REQUIRED)
set (SOURCES holes5.cpp)
add_executable(holes5 ${SOURCES})
set (SOURCES par_unseq.cpp)
add_executable(par_unseq ${SOURCES})
target_link_libraries(par_unseq PUBLIC TBB::tbb)
par_unseq.cpp:
#include <cstdint>
#include <iostream>
#include <chrono>
#include <cmath>
#include <numeric>
#include <utility>
#include <algorithm>
#include <execution>
using namespace std;
double f(double x) noexcept
{
const int N = 1000;
for (int i = 0; i < N; ++i) {
x = log2(x);
x = cos(x);
x = x * x + 1;
}
return x;
}
double sum(const vector<double>& vec)
{
double sum = 0;
for (auto x : vec)
sum += x;
return sum;
}
int main()
{
cout << "Hey! Your machine has " << thread::hardware_concurrency() << " cores!\n";
// Make an input vector.
const int N = 1000000;
vector<double> vecInput(N);
for (int i = 0; i < N; ++i)
vecInput[i] = i + 1;
{ // Case #1: Plain transform, no parallelism.
auto startTime = chrono::system_clock::now();
vector<double> vecOutput(N);
transform(vecInput.cbegin(), vecInput.cend(), vecOutput.begin(), f);
auto endTime = chrono::system_clock::now();
chrono::duration<double> diff = endTime - startTime;
cout << "1. sum = " << sum(vecOutput) << ", time = " << diff.count() << "\n";
}
{ // Case #2: Transform with parallel unsequenced.
vector<double> vecOutput(N);
auto startTime = chrono::system_clock::now();
transform(execution::par_unseq,
vecInput.cbegin(), vecInput.cend(), vecOutput.begin(), f);
auto endTime = chrono::system_clock::now();
chrono::duration<double> diff = endTime - startTime;
cout << "2. sum = " << sum(vecOutput) << ", time = " << diff.count() << "\n";
}
}
/* Output:
Hey! Your machine has 4 cores!
1. sum = 1.60346e+06, time = 43.7997
2. sum = 1.60346e+06, time = 10.8235
*/
According to the libstdc++ documentation (see Note 3), you must link -ltbb whenever you include the <execution> header.
If you don't actually use any of the functions from <execution>, or you do but the compiler manages to inline them all, then your program might link even without -ltbb. This might be dependent on a specific version of the header or library, compiler version, or compilation options. And even then, it does not guarantee that the program will work correctly. It could be that including the header changes the compilation in some way, and that -ltbb includes initialization code needed for this to work correctly. Even if it doesn't now, it might in the future.
So I think the answer is very simple: if you include the header, link the library. If you don't need the <execution> features, then don't include the header in the first place.

CGAL example cannot read input files?

this is my first stackoverflow question, so I hope the following text meets the question requirements. If not, please tell me what needs to be changed so I can adapt the question.
I'm new to CGAL and C++ in general. I would like to use CGAL 5.0.2 on a Macbook Pro early 2015 with macOS Catalina Version 10.15.4.
So to begin with, I followed the instruction steps given by the CGAL documentation using the package manager Homebrew. Since CGAL is a header-only library I configured it using CMake, as is recommended by the documentation.
It all worked out fine, so I went on trying the recommended examples given in the file CGAL-5.0.2.tar.xz, which is provided here. I'm particularly interested in the example Voronoi_Diagram_2.
Using the Terminal I executed the command -DCGAL_DIR=$HOME/CGAL-5.0.2 -DCMAKE_BUILD_TYPE=Release . in the example folder called Voronoi_Diagram_2. Then I executed the command make. All went well, no error messages were prompted. But executing the resulting exec file didn't produce any results.
After some research I managed to modify the code in a way that it prints the values of some variables. Problem seems to be that the input file which contains the line segments for which the voronoi diagramm shall be calculated is not correctly read.
The while loop which I highlighted in the code below by inserting //// signs seems not to be entered. That's why I assume that the variable ifs is empty, even though the input file "data1.svd.cin", which can be found in the folder "data" of the example, wasn't.
Does anyone have an idea for the reasons of this behaviour? Any help is appreciated.
This is the vd_2_point_location_sdg_linf.cpp file included in the example, which I modified:
// standard includes
#include <iostream>
#include <fstream>
#include <cassert>
// includes for defining the Voronoi diagram adaptor
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Segment_Delaunay_graph_Linf_filtered_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_Linf_2.h>
#include <CGAL/Voronoi_diagram_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_policies_2.h>
// typedefs for defining the adaptor
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Segment_Delaunay_graph_Linf_filtered_traits_2<K> Gt;
typedef CGAL::Segment_Delaunay_graph_Linf_2<Gt> DT;
typedef CGAL::Segment_Delaunay_graph_adaptation_traits_2<DT> AT;
typedef CGAL::Segment_Delaunay_graph_degeneracy_removal_policy_2<DT> AP;
typedef CGAL::Voronoi_diagram_2<DT,AT,AP> VD;
// typedef for the result type of the point location
typedef AT::Site_2 Site_2;
typedef AT::Point_2 Point_2;
typedef VD::Locate_result Locate_result;
typedef VD::Vertex_handle Vertex_handle;
typedef VD::Face_handle Face_handle;
typedef VD::Halfedge_handle Halfedge_handle;
typedef VD::Ccb_halfedge_circulator Ccb_halfedge_circulator;
void print_endpoint(Halfedge_handle e, bool is_src) {
std::cout << "\t";
if ( is_src ) {
if ( e->has_source() ) std::cout << e->source()->point() << std::endl;
else std::cout << "point at infinity" << std::endl;
} else {
if ( e->has_target() ) std::cout << e->target()->point() << std::endl;
else std::cout << "point at infinity" << std::endl;
}
}
int main()
{
std::ifstream ifs("data/data1.svd.cin");
assert( ifs );
VD vd;
Site_2 t;
// /////////// Inserted Comment ////////////////////////////////
std::cout << "In the following the insertion from ifs should take place" << std::flush;
// ///////////////// while loop which doesn't seem to be active //////////////////
while ( ifs >> t ) {
// Existing Code to insert the points in the voronoi structure
vd.insert(t);
// Inserted Code to check if while loop is entered
std::cout << "Entered while loop" << std::flush;
}
// ///////////////////////////////////////////////////////////////////////////////
ifs.close();
assert( vd.is_valid() );
std::ifstream ifq("data/queries1.svd.cin");
assert( ifq );
Point_2 p;
while ( ifq >> p ) {
std::cout << "Query point (" << p.x() << "," << p.y()
<< ") lies on a Voronoi " << std::flush;
Locate_result lr = vd.locate(p);
if ( Vertex_handle* v = boost::get<Vertex_handle>(&lr) ) {
std::cout << "vertex." << std::endl;
std::cout << "The Voronoi vertex is:" << std::endl;
std::cout << "\t" << (*v)->point() << std::endl;
} else if ( Halfedge_handle* e = boost::get<Halfedge_handle>(&lr) ) {
std::cout << "edge." << std::endl;
std::cout << "The source and target vertices "
<< "of the Voronoi edge are:" << std::endl;
print_endpoint(*e, true);
print_endpoint(*e, false);
} else if ( Face_handle* f = boost::get<Face_handle>(&lr) ) {
std::cout << "face." << std::endl;
std::cout << "The vertices of the Voronoi face are"
<< " (in counterclockwise order):" << std::endl;
Ccb_halfedge_circulator ec_start = (*f)->ccb();
Ccb_halfedge_circulator ec = ec_start;
do {
print_endpoint(ec, false);
} while ( ++ec != ec_start );
}
std::cout << std::endl;
}
ifq.close();
return 0;
}

Boost.X3: does not compile with std::optional<std::string>

The following parser does not compile when I use std::optional<std::string> for values of a -lexeme[+alpha] rule: something breaks in the attribute management.
The grammar works fine if instead of std::string I use int as a base type, it also works if I use twice std::string (i.e., no std::optional). However it does not work with boost::optional either. In the real grammar there is a difference between the absence of the string, and an empty string: I want to use std::optional (or its Boost predecessor).
The full example is available on Coliru, but here are the relevant bits:
struct pair_t
{
std::string first;
std::optional<std::string> second;
};
BOOST_FUSION_ADAPT_STRUCT(pair_t, first, second)
const auto pair_rule = lexeme[+alpha] >> -lexeme[+alpha] >> eoi;
for (std::string i: {"ab", "ab cd"})
{
auto res = pair_t{};
auto first = i.cbegin();
auto last = i.cend();
auto r = x3::phrase_parse(first, last, pair_rule, space, res);
if (r && first == last)
std::cout << i << ": " << res << '\n';
else
std::cout << i << ": failed\n";
}
My compiler reports:
clang++-mp-5.0 -std=c++17 -isystem /opt/local/include/ x3-optional.cc && ./a.out
In file included from x3-optional.cc:8:
In file included from /opt/local/include/boost/spirit/home/x3.hpp:14:
In file included from /opt/local/include/boost/spirit/home/x3/auxiliary.hpp:11:
In file included from /opt/local/include/boost/spirit/home/x3/auxiliary/any_parser.hpp:17:
/opt/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:180:9: error: no matching function
for call to 'move_to'
detail::move_to(std::move(src), dest
^~~~~~~~~~~~~~~
/opt/local/include/boost/spirit/home/x3/char/char_parser.hpp:31:29: note: in instantiation of
function template specialization 'boost::spirit::x3::traits::move_to<const char &,
std::__1::basic_string<char> >' requested here
x3::traits::move_to(*first, attr);
^

CGAL-4.8.1 Arrangements - Bezier Curves Save Arrangement to File Error

I am new to CGAL.
I tried to modify Examples/Arrangement_on_surfaces_2 Bezier_curves.cpp to save arrangement to file as shown below:
//! \file examples/Arrangement_on_surface_2/Bezier_curves.cpp
// Constructing an arrangement of Bezier curves.
#include <fstream>
#include <CGAL/basic.h>
#ifndef CGAL_USE_CORE
#include <iostream>
int main ()
{
std::cout << "Sorry, this example needs CORE ..." << std::endl;
return 0;
}
#else
#include <CGAL/Cartesian.h>
#include <CGAL/CORE_algebraic_number_traits.h>
#include <CGAL/Arr_Bezier_curve_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/IO/Arr_iostream.h>
#include "arr_inexact_construction_segments.h"
#include "arr_print.h"
typedef CGAL::CORE_algebraic_number_traits Nt_traits;
typedef Nt_traits::Rational NT;
typedef Nt_traits::Rational Rational;
typedef Nt_traits::Algebraic Algebraic;
typedef CGAL::Cartesian<Rational> Rat_kernel;
typedef CGAL::Cartesian<Algebraic> Alg_kernel;
typedef Rat_kernel::Point_2 Rat_point_2;
typedef CGAL::Arr_Bezier_curve_traits_2<Rat_kernel, Alg_kernel, Nt_traits>
Traits_2;
typedef Traits_2::Curve_2 Bezier_curve_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
//typedef CGAL::Arrangement_2<Traits_2> Arrangement;
int main (int argc, char *argv[])
{
// Get the name of the input file from the command line, or use the default
// Bezier.dat file if no command-line parameters are given.
const char *filename = (argc > 1) ? argv[1] : "Bezier.dat";
const char *outfilename = (argc > 1) ? argv[1] : "BezierOut.dat";
// Open the input file.
std::ifstream in_file (filename);
if (! in_file.is_open()) {
std::cerr << "Failed to open " << filename << std::endl;
return 1;
}
// Read the curves from the input file.
unsigned int n_curves;
std::list<Bezier_curve_2> curves;
Bezier_curve_2 B;
unsigned int k;
in_file >> n_curves;
for (k = 0; k < n_curves; k++) {
// Read the current curve (specified by its control points).
in_file >> B;
curves.push_back (B);
std::cout << "B = {" << B << "}" << std::endl;
}
in_file.close();
// Construct the arrangement.
Arrangement_2 arr;
insert (arr, curves.begin(), curves.end());
// Print the arrangement size.
std::ofstream out_file;
out_file.open(outfilename);
out_file << "The arrangement size:" << std::endl
<< " V = " << arr.number_of_vertices()
<< ", E = " << arr.number_of_edges()
<< ", F = " << arr.number_of_faces() << std::endl;
out_file << arr;
out_file.close();
return 0;
}
#endif
If I comment out the line out_file << arr; it works fine. Otherwise it generates a C2678 error in read_x_monotone_curve in Arr_text_formtter.h
I am using Visual Studio 15 x86.
Thank you for any help.
I solve this by modifying the print_arrangement(arr) routine in arr_print.h to save_arrangement(arr) with a std::ofstream in place of std::cout.
It appears that the << operator does not work.
If someone else has a better solution I am open to it.
Points of intersections in an arrangement of Bezier curves cannot be represented in an exact manner. Therefore, such an arrangement cannot be saved using the default export (<<) operator and the standard format.
The easiest solution is to store the curves, but this means that the arrangement must be recomputed each time the curves are read. Perhaps other solution could be devised, but they are not implemented.

wcout function does not print a french character

I am using the wcin in order to store a single character in a wchar_t. Then I try to print it with a wcout call and the french character 'é' : but I can't see it at my console.
My compiler is g++ 4.5.4 and my OS is Ubuntu 12.10 64 bits.
Here is my attempt (wideChars.cpp) :
#include <iostream>
int main(){
using namespace std;
wchar_t aChar;
cout << "Enter your char : ";
wcin >> aChar;
wcout << L"You entered " << aChar << L" .\n";
return 0;
}
When I lauch the programm :
$ ./wideChars
Enter your char : é
You entered .
So, what's wrong with this code ?
First, add some error checking. Test what does wcin.good() return after the input and what does wcout.good() return after the "You entered" print? I suspect one of those will return false.
What are your LANG and LC_* environment variables set to?
Then try to fix this by adding this at the top of your main(): wcin.imbue(std::locale("")); wcout.imbue(std::locale(""));
I do not have my Ubuntu at hand right now, so I am flying blind here and mostly guessing.
UPDATE
If the above suggestion does not help then try to construct locale like this and imbue() this locale instead.
std::locale loc (
std::locale (),
new std::codecvt_byname<wchar_t, char, std::mbstate_t>("")));
UPDATE 2
Here is what works for me. The key is to set the C locale as well. IMHO, this is a bug in GNU C++ standard library implementation. Unless I am mistaken, setting std::locale::global(""); should also set the C library locale.
#include <iostream>
#include <locale>
#include <clocale>
#define DUMP(x) do { std::wcerr << #x ": " << x << "\n"; } while (0)
int main(){
using namespace std;
std::locale loc ("");
std::locale::global (loc);
DUMP(std::setlocale(LC_ALL, NULL));
DUMP(std::setlocale(LC_ALL, ""));
wcin.imbue (loc);
DUMP (wcin.good());
wchar_t aChar = 0;
wcin >> aChar;
DUMP (wcin.good());
DUMP ((int)aChar);
wcout << L"You entered " << aChar << L" .\n";
return 0;
}
UPDATE 3
I am confused, now I cannot reproduce it again and setting std::locale::global(loc); seems to do the right thing wrt/ the C locale as well.