2

EDIT: Just for closure, this problem turned out to be due to a bug in the linker. Microsoft fixed it in release 17.4.3

I just updated my Visual Studio instance from 17.3.6 to 17.4.0. Then I tried a clean build of my solution. Suddenly one of my projects gives me linker errors

8>pch.obj : error LNK2001: unresolved external symbol __imp___tls_index_?init@?1??lazy_init_num_threads@internal@at@@YAXXZ@4_NA
8>pch.obj : error LNK2001: unresolved external symbol __imp___tls_offset_?init@?1??lazy_init_num_threads@internal@at@@YAXXZ@4_NA
8>C:\Users\jmole\Documents\Dev\Main\Solutions\..\Mobile\x64\Debug\net6.0-windows\mld_v143.dll : fatal error LNK1120: 2 unresolved externals

This completely confuses me. When I turn on verbose linking I see it finding all sorts of similar symbols in MSVCRTD.lib. For example.

2>      Found _tls_index
2>      Found __dyn_tls_init

Anyone else encountering this?

Joe
  • 5,394
  • 3
  • 23
  • 54
  • `__imp___tls_index_` is not `_tls_index`. Your project seems to wrongly switch between using dynamic or static C runtime, and the corresponding warning should be raised in the log prior those errors. – 273K Nov 08 '22 at 19:54
  • Is that what that name means? That it's trying to use a static function? Because this is the exact same code that built with 17.3.6. It has literally been a decade since I've needed to track down a non-obvious link error or decipher mangled names so it's tough for me to tell – Joe Nov 08 '22 at 19:56
  • Incidentally there does not seem to be any sort of warning about static vs dynamic. We have warnings set to be errors in our build settings – Joe Nov 08 '22 at 19:59
  • It's a linker warnings, it's not affected by compiler settings. – 273K Nov 08 '22 at 20:01
  • Try to change Runtime Library in the project settings. – 273K Nov 08 '22 at 20:02
  • Would vote as a dupe of https://stackoverflow.com/questions/5159353/how-can-i-get-rid-of-the-imp-prefix-in-the-linker-in-vc – 273K Nov 08 '22 at 20:03
  • Still confused. All projects share the exact same runtime library settings: Multithreaded Debug DLL. They all inherit it through the same property sheet. This project does not override that. More to the point, if I were linking improperly now it does not explain why this builds fine in 17.3.6 and not in 17.4.0 – Joe Nov 08 '22 at 20:06
  • 1
    They seemed to switch to a newer format of project settings database. I got many settings reset to defaults after update. So, you can't be sure the project settings are the same as they were in 17.3.6. Fortunately I use cmake and just have to regenerate the project. – 273K Nov 08 '22 at 20:34
  • I do appreciate the replies. (I hope I don't sound argumentative.) Obviously, something has changed but I don't think it is project settings. My C++ projects are Visual Studio only. No CMAKE files, just straight up Visual Studio `.VCXPROJ` and `.PROPS` files Nothing about them has changed. Even the interactive project-settings dialog, still tells me that the failing project is still using the same multithreaded runtime build settings. I guess I'll have to try to re-build all my 3rd party libraries (just headers and .LIB files) and see if that helps. – Joe Nov 08 '22 at 21:35
  • I have the same problem. I'm using CMake, but regeneration of the project doesn't solve the problem. It seems to me it depends on the linked libraries, because I got this link error with a specific project only. – Chris Stamm Nov 08 '22 at 22:51
  • VS 17.4 updates STL. It can be a reason, does something with possible moved thread local storage code. – 273K Nov 08 '22 at 23:46
  • @ChrisStamm The good news is we are very fortunate that they gave us the ability to go back to a previous version. That's what I had to do for now. I ran the installer, chose the "More" option and reverted back to 17.3.6. Everything builds now. I will have to fix it later after we do a release – Joe Nov 09 '22 at 00:39

3 Answers3

7

Go to the file under \Lib\site-packages\torch\include\ATen\Parallel.h in your python environment and edit it by removing the inline implementation of at::internal::lazy_init_num_threads() leaving only the declaration. This will force your build to use non-inline import. The issue is most probably in the way VS C++ handled inline exports having static variables - in this case thread_local one.

Perfect solution of course is rebuilding pytorch together with your extension (as would be the case with any C++ DLL "exporting" classes without really taking care about doing it in a safe ABI compatible way) but patching the include file is also OK here, it will just prevent the compiler from inlining the API and creating a reference to the local static thread_local variable that fails linking step later. The compiler will then use non-inline variant from the pytorch DLL and linker error will be done away with.

ProfNandaa
  • 3,210
  • 2
  • 18
  • 19
  • The version of PyTorch we are using now is just the already-built one downloaded from the official release. If I were to edit that header file but not build or download anything new, you think that merely making this header file change would work and be safe? I ask this first -- before trying it -- because in order to actually verify this I would need to update to version 13.4 again. Then I would need to revert back if it caused problems. – Joe Nov 14 '22 at 23:03
  • (Meant version 17.4) – Joe Nov 15 '22 at 00:30
  • I have the same problem with pytorch C++ version and it solves my problem. – kilasuelika Nov 25 '22 at 12:52
  • I was not able to actually make this change until today due to an impending software release. However I made it and can confirm it solved the problem. I still want to build it as was suggested first by @MSalters. But this did fix the immediate issue – Joe Dec 07 '22 at 21:06
  • I'm using Anaconda, so in my case the file was at `C:\Users\\AppData\Roaming\Python\Python39\site-packages\torch\include\ATen\Parallel.h`. Then I replaced everything from `inline TORCH_API void lazy_init_num_threads() {` down to the `}` with only this: `TORCH_API void lazy_init_num_threads();` and it worked. – Michael Innes Dec 13 '22 at 01:34
  • Turns out it was a bug in the linker, fixed in version 17.4.3: https://developercommunity.visualstudio.com/t/thread_local-causing-fatal-error-LNK1161/10199441 – Joe Dec 13 '22 at 20:23
1

The name mangling appears to point to at::internal::lazy_init_num_threads, which is a PyTorch function (a bit weird, but it might very well use thread-local storage). You may need to rebuild PyTorch with the same toolchain

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thank you. That is exactly what I was guessing but you confirmed it. And I would love to be able to build PyTorch. We use the non-GPU-optimized version that you can just download. That's what's giving me the link error. I would love to able to build it properly, with GPU-optimization turned on. Unfortunately my attempts to do so are not working out well. (It's why I had to go back to 17.3.6) I can't even get CMake to generate me a proper VS solution. Installed CUDA and all that. But I guess this is the topic for a different post if I cannot figure it out myself. – Joe Nov 11 '22 at 18:54
-4

After updating to 17.4, please switch to LLVM for Visual Studio 2022 in Platform Toolset to avoid such errors in linking.

PS: LLVM for Visual Studio 2017, 2019 and 2022: Visual-Studio-llvm-utils