Argmax of 2d vector on C++ - c++

I am working on python/pytorch and I have an example like
2d vector a
|
v
dim-0 ---> -----> dim-1 ------> -----> --------> dim-1
| [[-1.7739, 0.8073, 0.0472, -0.4084],
v [ 0.6378, 0.6575, -1.2970, -0.0625],
| [ 1.7970, -1.3463, 0.9011, -0.8704],
v [ 1.5639, 0.7123, 0.0385, 1.8410]]
|
v
Then, the argmax with the index of 1 will be
# argmax (indices where max values are present) along dimension-1
In [215]: torch.argmax(a, dim=1)
Out[215]: tensor([1, 1, 0, 3])
My question is that given the 2d vector a as above, how could I implement argmax function on C++ to give me same output as above? Thanks for reading
This is what I did
vector<vector<float>> a_vect
{
{-1.7739, 0.8073, 0.0472, -0.4084},
{0.6378, 0.6575, -1.2970, -0.0625},
{1.7970, -1.3463, 0.9011, -0.8704},
{1.5639, 0.7123, 0.0385, 1.8410}
};
std::vector<int>::iterator max = max_element(a_vect.begin() , a_vect.end()-a_vect.begin());

You can use std::max_element to find the index in each sub vector
#include <algorithm>
#include <iostream>
#include <vector>
using std::vector;
int main()
{
vector<vector<float>> a_vect=
{
{-1.7739, 0.8073, 0.0472, -0.4084},
{0.6378, 0.6575, -1.2970, -0.0625},
{1.7970, -1.3463, 0.9011, -0.8704},
{1.5639, 0.7123, 0.0385, 1.8410}
};
vector<int> max_index;
for(auto& v:a_vect)
max_index.push_back(std::max_element(v.begin(),v.end())-v.begin());
for(auto i:max_index)
std::cout << i << ' '; // 1 1 0 3
}

Related

How to remove the Nth element in a range?

I can write:
my_range | ranges::views::remove(3)
using the ranges-v3 library, to remove the element(s) equal to 3 from the range my_range. This can also be done in C++20 with
my_range | std::views::filter([](auto const& val){ return val != 3; })
But - how can I remove the element at position 3 in my_range, keeping the elements at positions 0, 1, 2, 4, 5 etc.?
Here's one way to do it:
#include <iostream>
#include <ranges>
#include <range/v3/view/take.hpp>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/concat.hpp>
int main() {
const auto my_range = { 10, 20, 30, 40, 50, 60, 70 };
auto index_to_drop = 3; // so drop the 40
auto earlier = my_range | ranges::views::take(index_to_drop - 1);
auto later = my_range | ranges::views::drop(index_to_drop);
auto both = ranges::views::concat(earlier, later);
for (auto const & num : both) { std::cout << num << ' '; }
}
This will produce:
10 20 30 50 60 70
... without the 40.
See it working on Godbolt. Compilation time is extremely poor though. Also, concat() is not part of C++20. Maybe in C++23?
The most straightforward way I can think of in range-v3 would be:
auto remove_at_index(size_t idx) {
namespace rv = ranges::views;
return rv::enumerate
| rv::filter([=](auto&& pair){ return pair.first != idx; })
| rv::values;
}
To be used like:
my_range | remove_at_index(3);
enumerate (and its more general cousin zip) is not in C++20, but will hopefully be in C++23.

Rcpp function for subsetting strings

I was wondering if there was an Rcpp function which takes an Rcpp::String data type as input and returns a given character (by index) of the string. For example, extracting the character at index 0 of the string. This would be equivalent to the string::at method from the string header in c++. I have written this:
#include <vector>
#include <string>
#include <Rcpp.h>
using namespace Rcpp;
typedef std::vector<std::string> stringList;
int SplitGenotypesA(std::string s) {
char a = s.at(0);
int b = a - '0';
return b;
}
But would prefer not to have to convert between Rcpp::String and std::string types.
You can feed an R vector of strings directly to C++ using Rcpp::StringVector. This will obviously handle single elements too.
Getting the nth character of the ith element of your vector is as simple as vector[i][n].
So, without using std::string you can do this:
#include<Rcpp.h>
// [[Rcpp::export]]
Rcpp::NumericVector SplitGenotypesA(Rcpp::StringVector R_character_vector)
{
int number_of_strings = R_character_vector.size();
Rcpp::NumericVector result(number_of_strings);
for(int i = 0; i < number_of_strings; ++i)
{
char a = R_character_vector[i][0];
result[i] = a - '0';
}
return result;
}
Now in R you can do:
SplitGenotypesA("9C")
# [1] 9
or better yet,
SplitGenotypesA(c("1A", "2B", "9C"))
# [1] 1 2 9
Which is even a little faster than the native R method of doing the same thing:
microbenchmark::microbenchmark(
R_method = as.numeric(substr(c("1A", "2B", "9C"), 1, 1)),
Rcpp_method = SplitGenotypesA(c("1A", "2B", "9C")),
times = 1000)
# Unit: microseconds
# expr min lq mean median uq max neval
# R_method 3.422 3.765 4.076722 4.107 4.108 46.881 1000
# Rcpp_method 3.080 3.423 3.718779 3.765 3.765 32.509 1000

4d mapping in C++ with tuple

This is somewhat similar to this problem 4d mapping in C++? and one of my previous questions on maps in C++ Use a map with the map name defined by a string C++
I have a code that looks like this (that does not work and stops at the line giving input to the map):
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <vector>
using namespace std;
int main()
{
map<string, //Volkswagen (car brand)
map<string, //series
map<int, //in this example 1
tuple<string, string>>>> mapMapMap;
string myCarmapMapMap = "Volkswagen";
int Number = 1;
mapMapMap[myCarmapMapMap]["3 series"][Number] = {90, 20};,
string Output;
Output.assign(get<0>(mapMapMap[myCarmapMapMap].find("3 series")->second));
cout << "\n" << "------------" << "\n" << Output << "\n"<< "------------" << "\n";
}
What I want to do is to assign two values to Volkswagen, 3 series, 1 and then be able to call it like:
Volkswagen -> 3 series -> 1 -> <0> (value 1).
This is the error message I get:
|19|error: expected primary-expression before ',' token|
I have also tried:
mapMapMap.insert({myCarmapMapMap, "3 series", Number, {"90", "20"}});
But it does not work either. How do I combine a 4d map with a tuple?
Change your assignment so it can actually form a tuple<string, string> (note the quotation signs on the right hand side):
mapMapMap[myCarmapMapMap]["3 series"][Number] = {"90", "20"};
Example
Also, remove the , at the end of the line.
Your query can, probably, be fixed by including the Number again, like:
string output = get<0>(mapMapMap[myCarmapMapMap].find("3 series")->second[Number]);

RcppEigen sparse matrix insert operation gives invalid class “dgCMatrix” error

I'm trying to get up to speed on using C++ to quickly build some sparse matrices for use in R. However, I cannot seem to use the insert method to change single elements of a sparse matrix in Eigen and get a correct R object of class dgCMatrix. A simple example is below.
The C++ code is:
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
using Eigen::SparseMatrix; // sparse matrix
// [[Rcpp::export]]
SparseMatrix<double> SimpleSparseMatrix(int n) {
SparseMatrix<double> new_mat(n, n);
new_mat.insert(0, 0) = 2;
Rcpp::Rcout << new_mat << std::endl;
return new_mat;
}
And the resulting R is:
> SimpleSparseMatrix(2)
2 0
0 0
2 x 2 sparse Matrix of class "dgCMatrix"
Error in validObject(x) :
invalid class “dgCMatrix” object: last element of slot p must match length of slots i and x
As you can see from stdout, eigen is doing the right thing. However, the resulting sparse matrix object is malformed. Indeed, looking at its slots show invalid values for p:
> foo <- SimpleSparseMatrix(2)
2 0
0 0
> str(foo)
Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
..# i : int 0
..# p : int [1:3] 0 2 4
..# Dim : int [1:2] 2 2
..# Dimnames:List of 2
.. ..$ : NULL
.. ..$ : NULL
..# x : num 2
..# factors : list()
Any ideas what might be going wrong?
After the insert statement add this statement:
new_mat.makeCompressed();

Nest vectors consumes to much memory in c++ [duplicate]

This question already has answers here:
Nested STL vector using way too much memory
(6 answers)
Closed 8 years ago.
I`m trying to figure out why my application consumes too much memory. Here it is:
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include <algorithm>
#include <vector>
#include <utility>
#include <assert.h>
#include <limits.h>
#include <time.h>
#include <tchar.h>
#include <random>
typedef unsigned __int32 uint;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<vector<uint>> arr(65536 * 16, vector<uint>());
mt19937 mt;
mt.seed(time(NULL));
uniform_int<uint> generator(0, arr.size() - 1);
for (uint i = 0; i < 10000000; i++)
{
for (uint j = 0; j < 16; j++)
{
uint bucketIndex = generator(mt);
arr[bucketIndex].push_back(i);
}
}
uint cap = 0;
for (uint i = 0; i < arr.size(); i++)
{
cap += sizeof(uint) * arr[i].capacity() + sizeof(arr[i]);
}
cap += sizeof(vector<uint>) * arr.capacity() + sizeof(vector<vector<uint>>);
cout << "Total bytes: " << cap << endl;
cout << "Press any key..." << endl;
cin.get();
}
I use Windows 7 64-bit and Visual Studio 2010, code is also compiled as 64-bit.
Code outputs the following in Debug and Release
Total bytes: 914591424
Looks correct (you can check it by hand), but memory manager shows that application consumes ~ 1.4 gigabytes of RAM.
Where did those 500 megabytes came from? Could you please give me an idea how to sort this out?
UPDATE
Problem is caused by memory fragmentation. Can be solved by compacting memory from time to time.
This is because each vector contains three pointers (or their moral and size equivalent): begin, begin + size, and begin + capacity. So when you have a vector containing tons of other small vectors, each inner vector wastes three words (so 24 bytes on a 64-bit system).
And since each inner vector's begin() points to a separate allocation, you have N times the allocation overhead cost to pay. That could be another several bytes.
Instead, you probably want to allocate a single large region and treat it like a 2D array. Or use one of the many libraries that offer such functionality. That won't work if your inner vectors are of different sizes, but often they are all one size, so you really want a 2D "rectangle" anyway, rather than a vector of vectors.
I've compared with Boost Container's vector. And added shrink_to_fit. The difference:
Total bytes: 690331672 // boost::container::vector::shrink_to_fit()
Total bytes: 1120033816 // std::vector
(Note also that boost containers never dynamically allocate on default construction.)
Here's the code (not much change, there):
#include <iostream>
#include <exception>
#include <algorithm>
#include <vector>
#include <utility>
#include <cassert>
#include <cstdint>
#include <random>
#include <boost/optional.hpp>
#include <boost/container/vector.hpp>
using boost::container::vector;
using boost::optional;
int main()
{
vector<vector<uint32_t>> arr(1<<20);
std::mt19937 mt;
mt.seed(time(NULL));
std::uniform_int_distribution<uint32_t> generator(0, arr.size() - 1);
for (uint32_t i = 0; i < 10000000; i++)
{
for (uint32_t j = 0; j < 16; j++)
{
auto& bucket = arr[generator(mt)];
//if (!bucket) bucket = vector<uint32_t>();
bucket.push_back(i);
}
}
for(auto& i : arr)
i.shrink_to_fit();
uint32_t cap = 0;
for (uint32_t i = 0; i < arr.size(); i++)
{
cap += sizeof(uint32_t) * arr[i].capacity() + sizeof(arr[i]);
}
cap += sizeof(vector<uint32_t>) * arr.capacity() + sizeof(arr);
std::cout << "Total bytes: " << cap << std::endl;
std::cout << "Press any key..." << std::endl;
std::cin.get();
}
Update memory profile run
--------------------------------------------------------------------------------
Command: ./test
Massif arguments: (none)
ms_print arguments: massif.out.4193
--------------------------------------------------------------------------------
MB
822.7^ #
| ###
| #####:
| #######:
| #########:
| :############:
| :::::##:############:
| ##:: ::# :############:
| #####:: ::# :############:
| ### ###:: ::# :############:
| :::#### ###:: ::# :############:
| ###:::: #### ###:: ::# :############:
| ##### :::: #### ###:: ::# :############:
| #### ### :::: #### ###:: ::# :############:
| ###:#### ### :::: #### ###:: ::# :############:
| ###### :#### ### :::: #### ###:: ::# :############:
| #### ### :#### ### :::: #### ###:: ::# :############:
| ######## ### :#### ### :::: #### ###:: ::# :############:
| :::::::## ##### ### :#### ### :::: #### ###:: ::# :############:
| ::#:#:::: ::: ## ##### ### :#### ### :::: #### ###:: ::# :############:
0 +----------------------------------------------------------------------->Gi
0 69.85
The problem is that you don't know the exact sizes for your arrays, otherwise you could set the vector capcities with reserve before actually filling them, this way you could avoid fragmentation. Try the following:
Generate the random seed (time(NULL)) and save it for later use.
Create an std::vector<uint> with array size 65536 * 16 and initialize all integers/counters in it to zero, lets name this array/vector "vec_sizes". We will use this array to store/find-out the size of your arrays that we will later create/fill-up.
Initialize a random generator with the seed acquired in step #1.
Run your algorithm (the nested for loops) but instead of storing an item into a 2D vector just like arr[bucketIndex].push_back(i); in your code just increase the vec_sizes[bucketIndex] counter.
Now we know the sizes of all vectors.
Create your arr vector.
for all subvectors in arr call the reserve method of the vector with the corresponding size found in the vec_sizes vector. This should preallocate the vectors effectively and you can avoid reallocations.
Initialize a random generator with the same seed we stored in step #1.
run your algorithm. Now pushing data into the vectors doesn't reallocate as their storage has already been allocated by your reserve calls.
Here we exploited the fact that you are using a pseudo random generator that gives the very same series of numbers if you run it twice starting with the same seed.
Note: Often when memory efficiency is the goal the solution is doing the work twice: First calculating different dimensions of the final data and then allocating space very effectively/"compactly" and then filling up the effectively allocated storage. usually you have to sacrifice something.