Tdarr icon indicating copy to clipboard operation
Tdarr copied to clipboard

GPU doing CPU tasks, and vice versa

Open my95z34 opened this issue 1 year ago • 4 comments

I just converted over to flows today. I'm having it rescan and attempt to convert files that had failed before. One thing I have noticed is that my GPU is doing all of the normal CPU tasks. And a current transcode that should be NVENC is being converted using the CPU. In the node options I do NOT have "Allow GPU workers to do CPU tasks" enabled, yet it's still doing them. Tasks such as reordering streams, cleaning audio, cleaning subtitles, etc.

My current flow: https://imgur.com/4sQU2GX

Node status: https://imgur.com/ZZOga23

Showing that it's doing the NVENC using the CPU: https://imgur.com/buQ4K2t

Copy of the log for a file transcoding on the CPU: https://hastebin.com/share/kucaretidu.swift

Any guidance as to what I have set up wrong here?

  • OS: Unraid (docker)
  • Browser: Chrome
  • Version 2.17.01

my95z34 avatar Feb 01 '24 00:02 my95z34

After doing a little bit of research, it's acting like there is no worker designation for flows like there is for plugins. It just grabs the first available worker and runs. Is that correct?

my95z34 avatar Feb 04 '24 21:02 my95z34

Yes that's right, with flows it's the idea that there's logic in the flow that will give a CPU worker CPU related transcode args and a GPU worker GPU transcode related args. For example using the 'Encode Video' plugin has logic within it to do this. The classic plugins do not have this logic so might be the case that a CPU worker runs GPU args or vice versa. You can use the Check Node Hardware Encoder flow plugin so that when GPU hardware is available it will do GPU transcoding. Can also use the Check Flow Variable to check the worker type and act accordingly.

HaveAGitGat avatar Feb 29 '24 00:02 HaveAGitGat

Yes that's right, with flows it's the idea that there's logic in the flow that will give a CPU worker CPU related transcode args and a GPU worker GPU transcode related args. For example using the 'Encode Video' plugin has logic within it to do this. The classic plugins do not have this logic so might be the case that a CPU worker runs GPU args or vice versa. You can use the Check Node Hardware Encoder flow plugin so that when GPU hardware is available it will do GPU transcoding. Can also use the Check Flow Variable to check the worker type and act accordingly.

I'm not sure I'm following. When I use classic plugins, they are correctly using gpu and cpu workers. The cpu workers will do audio cleaning, subtitle cleaning, etc. And the gpu will only do transcoding. But when I set up the flows, no matter what I tried cpu and gpu would both do the same tasks. Cpu would be transcoding, even tho it was specified to be NVENC. And gpu would be doing subtitle and audio cleaning. It was just grabbing whatever worker was available, not caring about whether it was cpu or gpu.

I will look into the check node hardware encoder stuff when I get a chance. Could you elaborate on it?

my95z34 avatar Feb 29 '24 05:02 my95z34

The classic plugins do not have this logic

i believe it depends if the plugin autor took care and implemented this part.

take my classic plugin below, for example. It will check if there is GPU available and if its a GPU worker and set the ffmpeg parameters accordingly.

if its a CPU worker, it will not fail; will just fallback to transcode using CPU parameters, automagically.

https://github.com/yodog/tdarr/blob/main/Tdarr_Plugin_yodog_scale_and_transcode.js

yodog avatar Mar 02 '24 18:03 yodog

"if its a CPU worker, it will not fail; will just fallback to transcode using CPU parameters, automagically." which isnt ideal... it should wait?

Question is, does this matter speed wise? If its a significant performance improvement, then it would be cool if tdarr would send requests to CPU/GPU depending on the work to do. If there is no worker free, it needs to wait. (maybe a condition with expected runtime could be implemented...)

CurlyFlow avatar Apr 11 '24 12:04 CurlyFlow

@CurlyFlow yes that will be added soon, the system is mostly in place under the hood already.

HaveAGitGat avatar May 09 '24 06:05 HaveAGitGat

@my95z34

This is what I'd do:

image

So first we check the workerType, and if it's transcodecpu worker we do CPU transcoding with classic plugin, if not then we double check that the node is able to do nvenc transcoding and if so then do GPU transcoding (other worker type is called transcodegpu FYI).

image

You can copy and import this flow to try it, I will add it to the flow templates:

{
  "name": "Dynamic Classic",
  "description": "Dynamic Classic",
  "tags": "",
  "flowPlugins": [
    {
      "name": "Input File",
      "sourceRepo": "Community",
      "pluginName": "inputFile",
      "version": "1.0.0",
      "id": "7a6heYJTK",
      "position": {
        "x": 619.59375,
        "y": 71
      }
    },
    {
      "name": "Check Flow Variable Worker Type",
      "sourceRepo": "Community",
      "pluginName": "checkFlowVariable",
      "version": "1.0.0",
      "id": "Xmz-M1Kcp",
      "position": {
        "x": 619.365588981588,
        "y": 198.5575740188268
      },
      "inputsDB": {
        "variable": "{{{args.workerType}}}",
        "value": "transcodecpu"
      }
    },
    {
      "name": "Run Classic Transcode Plugin GPU",
      "sourceRepo": "Community",
      "pluginName": "runClassicTranscodePlugin",
      "version": "1.0.0",
      "id": "eqw2BDcZn",
      "position": {
        "x": 744.2234764236456,
        "y": 576.0927759290009
      }
    },
    {
      "name": "Run Classic Transcode Plugin CPU",
      "sourceRepo": "Community",
      "pluginName": "runClassicTranscodePlugin",
      "version": "1.0.0",
      "id": "UINSF-Jto",
      "position": {
        "x": 404.7683242434599,
        "y": 599.739336347842
      },
      "inputsDB": {
        "pluginSourceId": "Community:Tdarr_Plugin_MC93_Migz1FFMPEG_CPU"
      }
    },
    {
      "name": "Check Node Hardware Encoder",
      "sourceRepo": "Community",
      "pluginName": "checkNodeHardwareEncoder",
      "version": "1.0.0",
      "id": "kgwN6R1_i",
      "position": {
        "x": 769.900492466526,
        "y": 348.6591157806557
      }
    },
    {
      "name": "Replace Original File",
      "sourceRepo": "Community",
      "pluginName": "replaceOriginalFile",
      "version": "1.0.0",
      "id": "lxwMPh0uu",
      "position": {
        "x": 624.1582866864101,
        "y": 833.8283054574069
      }
    },
    {
      "name": "Require Review",
      "sourceRepo": "Community",
      "pluginName": "requireReview",
      "version": "1.0.0",
      "id": "SWsh_Z7oE",
      "position": {
        "x": 624.1582866864101,
        "y": 754.5681189626113
      }
    }
  ],
  "flowEdges": [
    {
      "source": "7a6heYJTK",
      "sourceHandle": "1",
      "target": "Xmz-M1Kcp",
      "targetHandle": null,
      "id": "9qpseUiC8"
    },
    {
      "source": "Xmz-M1Kcp",
      "sourceHandle": "1",
      "target": "UINSF-Jto",
      "targetHandle": null,
      "id": "uidvJfV-Y"
    },
    {
      "source": "Xmz-M1Kcp",
      "sourceHandle": "2",
      "target": "kgwN6R1_i",
      "targetHandle": null,
      "id": "BjUAnQVoT"
    },
    {
      "source": "kgwN6R1_i",
      "sourceHandle": "1",
      "target": "eqw2BDcZn",
      "targetHandle": null,
      "id": "6naXep3GD"
    },
    {
      "source": "kgwN6R1_i",
      "sourceHandle": "2",
      "target": "UINSF-Jto",
      "targetHandle": null,
      "id": "MVgJ6Jw8v"
    },
    {
      "source": "UINSF-Jto",
      "sourceHandle": "1",
      "target": "SWsh_Z7oE",
      "targetHandle": null,
      "id": "IybAjMLOh"
    },
    {
      "source": "eqw2BDcZn",
      "sourceHandle": "1",
      "target": "SWsh_Z7oE",
      "targetHandle": null,
      "id": "Ye3W2wE5Y"
    },
    {
      "source": "SWsh_Z7oE",
      "sourceHandle": "1",
      "target": "lxwMPh0uu",
      "targetHandle": null,
      "id": "HSogWrrs9"
    }
  ]
}

HaveAGitGat avatar May 09 '24 06:05 HaveAGitGat

This template has been added: image

Let me know if you need any more help.

HaveAGitGat avatar May 09 '24 06:05 HaveAGitGat

@HaveAGitGat I appreciate that. Just out of curiosity, how would I arrange that flow so that it would try to convert the video using NVENC, and if it fails, then try CPU, and if that fails, then just fail? I'm having a mental block....

my95z34 avatar May 09 '24 12:05 my95z34

as far as i see he posted a flow already... (but didnt i tried)

CurlyFlow avatar May 09 '24 22:05 CurlyFlow

as far as i see he posted a flow already... (but didnt i tried)

The one that was just posted? As far as I can tell, from my limited experience with flows, all that is doing is checking the worker type that is available and then transcoding using that worker. There is no failure plan.

my95z34 avatar May 09 '24 22:05 my95z34

@my95z34 you try the gpu transcode and then connect the error handle to the cpu plugin:

image

Flow Example { "name": "Basic HEVC Video Flow", "description": "Basic HEVC Video Flow", "tags": "", "flowPlugins": [ { "name": "Input File", "sourceRepo": "Community", "pluginName": "inputFile", "version": "1.0.0", "id": "pE6rU7gkW", "position": { "x": 758.5809635618224, "y": 117.19206188888086 } }, { "name": "Check if hevc", "sourceRepo": "Community", "pluginName": "checkVideoCodec", "version": "1.0.0", "id": "91b7IrsEc", "position": { "x": 672.4549563302081, "y": 253.11148102973914 } }, { "name": "Replace Original File", "sourceRepo": "Community", "pluginName": "replaceOriginalFile", "version": "1.0.0", "id": "4fkfOyR3l", "position": { "x": 820.4549563302082, "y": 742.2114810297393 } }, { "name": "Run Classic Transcode Plugin GPU", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "1.0.0", "id": "cyhNCt1ih", "position": { "x": 386.9480559951306, "y": 423.3493807189681 } }, { "name": "Run Classic Transcode Plugin CPU", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "1.0.0", "id": "wtmaZzr3E", "position": { "x": 545.0613029173174, "y": 518.1139988993492 }, "inputsDB": { "pluginSourceId": "Community:Tdarr_Plugin_MC93_Migz1FFMPEG_CPU" } } ], "flowEdges": [ { "source": "pE6rU7gkW", "sourceHandle": "1", "target": "91b7IrsEc", "targetHandle": null, "id": "HhF4rw2DZ" }, { "source": "91b7IrsEc", "sourceHandle": "1", "target": "4fkfOyR3l", "targetHandle": null, "id": "W2nVG7ts5" }, { "source": "91b7IrsEc", "sourceHandle": "2", "target": "cyhNCt1ih", "targetHandle": null, "id": "ZWX9rMuJZ" }, { "source": "cyhNCt1ih", "sourceHandle": "1", "target": "4fkfOyR3l", "targetHandle": null, "id": "hLYGZziuF" }, { "source": "cyhNCt1ih", "sourceHandle": "err1", "target": "wtmaZzr3E", "targetHandle": null, "id": "HpKUPIW52" }, { "source": "wtmaZzr3E", "sourceHandle": "1", "target": "4fkfOyR3l", "targetHandle": null, "id": "FfJSMv1Je" } ] }

HaveAGitGat avatar May 10 '24 05:05 HaveAGitGat

@HaveAGitGat Using the flow you just shared, I'm still getting the weirdness where CPU is running the GPU transcode, and vice versa.

tdarr

my95z34 avatar May 10 '24 13:05 my95z34

@HaveAGitGat Using the flow you just shared, I'm still getting the weirdness where CPU is running the GPU transcode, and vice versa.

tdarr

Although, looking at the FPS, maybe it is using the GPU even though it says CPU, and whatnot. I'm so damn confused, lol

my95z34 avatar May 10 '24 14:05 my95z34

The flow in my last message is not for CPU/GPU worker differentiation, it was for your question of how to attempt a GPU transcode and then if that fails fallback to CPU transcoding. You need to use the flow further up for CPU/GPU worker differentiation where the flow is checking the worker type at the beginning. You can combine both flows.

HaveAGitGat avatar May 10 '24 15:05 HaveAGitGat

The flow in my last message is not for CPU/GPU worker differentiation, it was for your question of how to attempt a GPU transcode and then if that fails fallback to CPU transcoding. You need to use the flow further up for CPU/GPU worker differentiation where the flow is checking the worker type at the beginning. You can combine both flows.

Oh, gotcha.

Well, I'm sorry to be so needy, but could you help me with that part? I guess I don't understand where the worker check would go, in relation to the failure line. I'm sorry! 🤦🏼‍♂️

my95z34 avatar May 10 '24 15:05 my95z34

I guess my difficulty in understanding comes with how each step is performed. Does one worker go down each step until completion, or does the flow evaluate each step individually and assign, potentially, a different worker at each step?

my95z34 avatar May 10 '24 18:05 my95z34