天天看點

Mac 使用 OpenMP/Clang

建立 hello.cpp 檔案:

#include <omp.h>
#include <stdio.h>
int main() {
    #pragma omp parallel
    printf("Hello from thread %d, nthreads %d\n", omp_get_thread_num(), omp_get_num_threads());
    return 0;
}
           

編譯會遇到如下錯誤:

hello.cpp:1:10: fatal error: 'omp.h' file not found
#include <omp.h>
          ^~~~~~
1 error generated.
           

因為預設的 g++ 編譯器不支援 openmp,我們可以設定 LLVM/Clang 編譯器來編譯 openmp。

執行以下指令:

brew install llvm # 安裝 LLVM 編譯器
brew install libomp # 安裝 OpenMP 庫
echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile # 将 llvm 的可執行檔案添加到 PATH 目錄
           

然後執行

clang -fopenmp hello.cpp -o hello
./hello
           

我的CPP檔案中用到了STL 中的 vector,然後就遇到了新的錯誤:

Undefined symbols for architecture x86_64:
  "std::__1::__vector_base_common<true>::__throw_length_error() const", referenced from:
      std::__1::vector<int, std::__1::allocator<int> >::assign(unsigned long, int const&) in seq-3efcea.o
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      void std::__1::vector<int, std::__1::allocator<int> >::__push_back_slow_path<int>(int&&) in seq-3efcea.o
  "std::logic_error::logic_error(char const*)", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "std::length_error::~length_error()", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
      _main in seq-3efcea.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::insert(unsigned long, char const*)", referenced from:
      _main in seq-3efcea.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
      _main in seq-3efcea.o
  "std::terminate()", referenced from:
      ___clang_call_terminate in seq-3efcea.o
  "typeinfo for std::length_error", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "vtable for std::length_error", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "operator delete(void*)", referenced from:
      std::__1::__vector_base<int, std::__1::allocator<int> >::~__vector_base() in seq-3efcea.o
      std::__1::__deque_base<int, std::__1::allocator<int> >::~__deque_base() in seq-3efcea.o
      std::__1::__deque_base<int, std::__1::allocator<int> >::clear() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*> >::~__split_buffer() in seq-3efcea.o
      std::__1::__vector_base<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::~__vector_base() in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::~__split_buffer() in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      ...
  "operator new(unsigned long)", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "___cxa_allocate_exception", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "___cxa_begin_catch", referenced from:
      ___clang_call_terminate in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*> >::shrink_to_fit() in seq-3efcea.o
  "___cxa_end_catch", referenced from:
      std::__1::__split_buffer<int*, std::__1::allocator<int*> >::shrink_to_fit() in seq-3efcea.o
  "___cxa_free_exception", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "___cxa_throw", referenced from:
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::__split_buffer<int, std::__1::allocator<int>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int>&) in seq-3efcea.o
      std::__1::deque<int, std::__1::allocator<int> >::__add_back_capacity() in seq-3efcea.o
      std::__1::__split_buffer<int*, std::__1::allocator<int*>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<int*>&) in seq-3efcea.o
  "___gxx_personality_v0", referenced from:
      _main in seq-3efcea.o
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::vector(unsigned long, std::__1::vector<int, std::__1::allocator<int> > const&) in seq-3efcea.o
      std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::vector(std::__1::vector<int, std::__1::allocator<int> > const&) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::allocate(unsigned long) in seq-3efcea.o
      std::__1::vector<int, std::__1::allocator<int> >::vector(unsigned long, int const&) in seq-3efcea.o
      void std::__1::vector<int, std::__1::allocator<int> >::__push_back_slow_path<int>(int&&) in seq-3efcea.o
      ...
ld: symbol(s) not found for architecture x86_64
clang-6.0: error: linker command failed with exit code 1 (use -v to see invocation)
           

是因為我們編譯的是 C++檔案,clang 沒有連結 STL 庫是以出錯了,我們可以顯式地連結标準庫:

clang -fopenmp hello.cpp -o hello -lstdc++
#或者 clang -fopenmp hello.cpp -o hello -lc++
./hello 
           

也可以直接用 clang++:

clang++ -fopenmp hello.cpp -o hello
./hello 
           

┆涼┆暖┆降┆等┆幸┆我┆我┆裡┆将┆ ┆可┆有┆謙┆戮┆那┆ ┆大┆始┆ ┆然┆

┆薄┆一┆臨┆你┆的┆還┆沒┆ ┆來┆ ┆是┆來┆遜┆沒┆些┆ ┆雁┆終┆ ┆而┆

┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆沒┆ ┆你┆

┆ ┆這┆ ┆試┆方┆在┆逃┆ ┆會┆ ┆在┆ ┆清┆來┆準┆ ┆沒┆有┆ ┆沒┆

┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆這┆ ┆晨┆ ┆的┆ ┆有┆來┆ ┆有┆

┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆這┆ ┆裡┆ ┆沒┆ ┆殺┆ ┆來┆ ┆ ┆來┆