Переменная не входит в область действия лямбда - PullRequest
0 голосов
/ 28 мая 2020

Я пытаюсь диагностировать проблему синхронизации на многоядерном процессоре [Xeon Silver]. Я думаю, что часы не настроены и не синхронизированы между процессором. Я использую примеры потоковой передачи Эли Бендерски [указано в фрагменте кода] для создания тестового инструмента. Я сделал три изменения. Я сначала заставил засыпать, добавил вызов std :: chrono :: system_clock :: now () и попытался распечатать его. Я собираю с помощью g cc 4.8.5 на CentOS 7.5.

Код выглядит следующим образом:

// // Eli Bendersky [http://eli.thegreenplace.net]
// This code is in the public domain.
#include <algorithm>
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <pthread.h>

int main(int argc, const char** argv) {
  unsigned num_cpus = std::thread::hardware_concurrency();
  std::cout << "Launching " << num_cpus << " threads\n";

  // A mutex ensures orderly access to std::cout from multiple threads.
  std::mutex iomutex;
  std::vector<std::thread> threads(num_cpus);
  for (unsigned i = 0; i < num_cpus; ++i)
  {
    threads[i] = std::thread([&iomutex, i]
    {
       // Simulate important work done by the tread by sleeping for a bit...
      std::this_thread::sleep_for(std::chrono::milliseconds(200));
      {
         std::chrono::time_point ti = std::chrono::system_clock::now();
         // Use a lexical scope and lock_guard to safely lock the mutex only for
         // the duration of std::cout usage.
         std::lock_guard<std::mutex> iolock(iomutex);
         std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch() << "\n";
       }
    });
  }

  for (auto& t : threads) {
      t.join();
  }
  return 0;
}

Я собираю с помощью make:

CXX = g++
CXXFLAGS = -std=c++11 -Wall -O3 -g -DNDEBUG -pthread
LDFLAGS = -lpthread -pthread

clock-check: clock-check.cpp
    $(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS)

G CC дает мне следующую ошибку:

[user@sbc1 concur]$ make clock-check
g++ -std=c++11 -Wall -O3 -g -DNDEBUG -pthread clock-check.cpp -o clock-check -lpthread -pthread
clock-check.cpp: In lambda function:
clock-check.cpp:32:67: error: ‘ti’ was not declared in this scope
      std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch() << "\n";
                                                               ^
make: *** [clock-check] Error 1

ti явно находится в той же области блока, что и оператор печати, и я сбит с толку, почему компилятор жалуется. Я не обнаружил никаких ограничений для переменных, локальных для лямбда. Большинство из того, что я нашел, было отсылкой к отловам.

Ответы [ 3 ]

1 голос
/ 28 мая 2020

Ваша проблема заключается в этой строке:

std::chrono::time_point ti = std::chrono::system_clock::now();

std::chrono::time_point ожидайте аргумент типа (например, std::chrono::time_point<std::chrono::system_clock>)

Предпочитайте использовать auto в этом случае:

auto ti = std::chrono::system_clock::now();

Тогда у вас будет ошибка, так как вы попытаетесь вывести std::chrono::duration в поток вывода.

Вы должны сделать:

std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch().count() << "\n";
1 голос
/ 28 мая 2020

Кажется, это ошибка в старых версиях g cc. С g cc 10.1 (--std = c ++ 11) я получаю ошибку :

<source>: In lambda function:   
<source>:23:34: error: missing template arguments before 'ti'    
   23 |          std::chrono::time_point ti = std::chrono::system_clock::now();    
      |                                  ^~    
<source>:27:67: error: 'ti' was not declared in this scope; did you mean 'i'?    
   27 |          std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch() << "\n";    
      |                                                                   ^~    
      |            

Ошибка об отсутствующем параметре шаблона (который отсутствует с g cc 4.5.8) в объявлении объясняет вторую ошибку.

Как ни странно g cc 4.8.5 с -std = c ++ 11 успешно компилирует код, если вы удалите строку с std::cout: https://godbolt.org/z/6LREHF

0 голосов
/ 28 мая 2020

Вывод шаблона класса недоступен до c ++ 17, поэтому вам необходимо указать параметры шаблона для chrono::timepoint. В качестве альтернативы используйте auto:

 auto ti = std::chrono::system_clock::now();

Кроме того, вы пытаетесь передать поток типа chrono::duration, что невозможно. Используйте ti.time_since_epoch().count().

Живой пример

...