Skip to content
This repository was archived by the owner on Oct 12, 2023. It is now read-only.
This repository was archived by the owner on Oct 12, 2023. It is now read-only.

Low-priority task reliability #314

Closed

Description

@simon-tarr

Hello,

I exclusively use low priority VMs; as an academic on a tight budget. I'm aware that low priority VMs are subject to be pre-empted at at point - I accept this as part of the deal.

Despite this, I'm finding that my long-running jobs (~20 hours) require frustrating levels of babysitting. My models keep failing at "random" points which I've now determined are to do with nodes being pre-empted. I've written my code such that, if a node is pre-empted and an iteration of my loop fails, the loop stops working and my cluster is deleted so that I'm no longer billed. This is annoying but, ultimately, doesn't really cost too much of my budget as the cluster is destroyed. I can reboot it again when I get into the office the following morning. Am I correct in thinking that, if a node is pre-empted, the task should be paused and rescheduled, to be picked up again when there's available capacity? I believe this to be the case and, on the whole, I think this is what usually happens. But I do regularly check my running jobs and find that they've crashed at some point or another. I'm certain it's not a problem with a particular iteration of my model - if I restart the job and where it previously crashed, it will complete successfully (this is why I think it's a problem with node preemption as opposed to a problem with my model).

If a merge task node gets pre-empted mid-merge, I think the merge task gets stuck. My R console looks like this. I've found that if a node within the cluster is still showing as 'running' (the hung merge task) I can reboot the node from portal.azure.com and the merge task will eventually show that is has completed within the R console. Sometimes, though, my R console will look like the above but all nodes within the cluster will be 'idle' - there's therefore no 'running' VM to restart so I have to rebuild the entire cluster and restart the whole job. This is obviously a problem because I could be running 1024 cores overnight with none of my work getting computed as the task has hung. If this happens early in the number of iterations I have to run, I waste hundreds of hours of compute time. This scenario has happened countless times to me and, cumulatively, I've wasted many hundreds of hours of compute time with groups of clusters sat there 'idle' for 8+ hours.

Is it possible to improve the reliability of preemption and the merge task or is this just the nature of the beast when it comes to using low-priority VMs? I should add that I keep my long running jobs as an active R session, rather than letting them run entirely in the cloud before downloading the entire job. The jobs don't take days to run and I like to keep an eye on their progress while I work on other things. To improve reliability, would it be advised to run these as long running jobs like here, or will I still experience an issue because, fundamentally, the problem is due to preempted nodes?

Thanks,
Simon

Activity

  1. brnleehng commented on Oct 1, 2018

    @brnleehng
    Collaborator

    Hi Simon,

    1. Yes. When a task gets interrupted by a preempted VM, Batch will detect this and requeue the task to run again. The task will then be scheduled whenever a VM is available. Then the task will be re run again. This means the task has to be idempotent.
    • What do you mean by restart the job and where it previously crashed? Do you mean you start the foreach loop at an certain iteration point and it'll work?
    • Is the iteration of the foreach loop failing because of the preempted VM? Are there logs for the task failure that I can investigate?
    1. Are you running your clusters at a fix amount of VMs? Perhaps you can run it with autoscale with VMs scaling down to 1 for the VM.

    How much data are the task results? If the disks are full, the VM runs into issues of changing its state.

    I would recommend disabling the merge task and run a separate job to merge the results. Are you running with chunksize greater than 1? This will get you partial merge results. If the results are quite large or too many, the R session in the merge task can hit a memory issue since it has to hold all of the results in memory for merging anyways.

    1. We can add more feedback on the merge task. Possibly write more logs to the stdout so users can see what the state of the merge task. However, this will slow down the merge task even more.. One benefit of using long running jobs instead of an active R session is you can submit all your jobs at once instead of waiting for each job to be done so then you don't need to wait for the 'hung' merge task.

    Is the hung merge task getting preempted then it gets rescheduled and then becomes hung again?
    Is each job dependent of each other?

    Unfortunately, I think this is the nature of low priority VMs. The maximum lifetime of the low priority VMs are generally 24 hours.

    You can reach out to razurebatch@microsoft.com for more detailed situations. I would be interested in learning more about your workflow scenario.

    Thanks for your feedback,
    Brian

  2. simon-tarr commented on Oct 1, 2018

    @simon-tarr
    Author

    Hi Brian, thanks very much for the detailed response - it's very much appreciated.

    I can't answer many of your questions immediately but you've given me plenty to think about. I'll run some tests and calculate how much memory etc the jobs are taking up. They're reasonably large but probably not so large that the cluster sizes I'm dealing with can't handle it. I am using a chunksize >1 (chunksize is always 130 in my current use case).

    With regards to your first bullet point; that is what I meant, yes. Essentially, the crashing isn't anything to do with any particular model. They will all run eventually if I restart the cluster and try again. So it's not like I'm working with a faulty model that can't run given the input parameters (e.g. a model that can't converge for whatever reason). I believe the crashing is an Azure problem - whether this is memory, pre-empted nodes etc etc.

    If you could let me know the exact logs that you'll need then I can take some time to grab these the next time it crashes.

    If it's not too much trouble, could you please explain how I can disabling the merge task and run a separate job to merge the results? Is this documented somewhere? I'd be happy to give this a go.

    Finally, the reliability has been pretty decent until a few weeks back which makes me think that something has changed on the backend...I rarely encountered this issues a month ago. Now every other job seems to crash for one reason or another. I know that's a bit of a hand-wavey statement in lieu of error logs but, subjectively, something has defintely changed.

  3. brnleehng commented on Oct 3, 2018

    @brnleehng
    Collaborator

    The merge task processes each file one by one, adding it to a list. If you are submitting jobs one by one, then the merge task will block the other job submissions, wasting core hours.

    If the merge task appears to be hung, can you give me the job id so I can check our event logs? I'll see if the service made any changes..
    Aren't these tasks idempotent? So you should let the tasks get re queued and be assign to another VM
    What's the average duration of these tasks?

    Here's a sample I wrote of disabling the merge task and combining the results locally.

    setAutoDeleteJob(value = FALSE)
    setCredentials("credentials.json")
    
    cluster <- makeCluster("cluster.json")
    registerDoAzureParallel(cluster)
    results <- vector("list", 3)
    for(i in 1:length(results)){
      start = results * i
      end = start + 3
      
      results[[i]] <- foreach(i = start:end, .options.azure = list(enableCloudCombine = FALSE,
                                                             wait = FALSE,
                                                             job = paste0("job"-i))) %dopar% {
        
      }
    }
    
    # Wait for jobs to complete
    
    for(i in 1:length(results)){
      results <- getJobResult(results[[i]])
    }

    Thanks,
    Brian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions