Data analysis code (finds coincidences in three sets of data)
Undefined behavior
There's UB in case when empty vector passed to the binary_search.
unsigned int mid;

it is uninitialised and will pop whatever compiler think he want in release mode. To solve this issue it is require initialise value with some error value (usually it is ~0 but you can choose your own), or use std::optional (c++17) and handle error case in lambda.
probably it is not an issue if vectors guaranteed to be non-empty and there's at least one proper value inside them.
mix of signed and unsigned types
Return type of binary_search is int, but branches can be unsigned int.
As it is actually return position in vector best way to use special unsigned integral type macro size_t meant to be used like this. So final check will be like.
...
constexpr size_t ERR = ~0;
siz_t res_i = binary_search(vec2, tstamp);
if (ERR == res_i) return; // early exit from lambda
...

But that kind of handling raise question about how to handle res_i-- if binary search return position 0. It probably will return INT_MAX for according integral type, but that kind of subtraction is implementation defined behavior so result defined by compiler.
potential out of bounds
if binary search return 0 position access to -1 will crash your program.
double r = dabs(tstamp-vec2[res_i-1]);

tightly related to previous issues.
probably it is not an issue if found position never meant to be 0
unnecessary variable reusing
If your program don't meant to be run on some embed device this kind of optimization basically do nothing - compilers usually smart enough to get rid of it by themselves. Probably good idea create some small function and p,q,r manipulations in it. Also it will prevent chance to make copy-paste errors
size_t someRoutine(double tstamp, const auto&amp; vec, size_t res) {
  double p = dabs(tstamp-vec[res]); 
  double q = dabs(tstamp-vec[res+1]); 
  double r = dabs(tstamp-vec[res-1]);
        
  if(r&lt;q &amp;&amp; r&lt;p) return res-1;
  if(q&lt;r &amp;&amp; q&lt;p) return res+1;
  return res;
}
//...
res_i = someRoutine(tstamp, vec2, res_i);
res_j = someRoutine(tstamp, vec3, res_j);


structs clearer than vector
it is good idea to create a struct instead of using a vector - less memory print, clearer usage.
struct SomData{
  double tstamp, vec2,vec3, first, second, third, fourth;
};
//...
coincidences.push_back({tstamp, vec2[res_i], vec3[res_j], first, second, third, fourth});
// OR
// coincidences.emplace_back(tstamp, vec2[res_i], vec3[res_j], first, second, third, fourth); // construct struct in-place, 
//...
std::sort(coincidences.begin(), coincidences.end(),
   [](const SomData&amp; A, const SomData&gt;&amp; B){
            return A.fourth &lt; B.fourth;
});
///...
cache.insert(pair.vec2);cache.insert(pair.vec3);

no need to use find if you don't need an iterator
maps ands sets have convenient method count which represents amount of items found by the key. You just need to check whether its zero or one
if(cache.count(pair.vec2) == 0 &amp;&amp; cache.count(pair.vec3) == 0) {
  std::cout &lt;&lt; &quot;Coincidence found!\n&quot;;
  cache.insert(pair.vec2);
  cache.insert(pair.vec3);
}

cycle copy elements
probably just missed &amp;
for(const auto&amp; pair : coincidences){