diff --git a/internal/calloc/CmdArgParser.go b/internal/calloc/CmdArgParser.go index 393c53ce..a5496f1c 100644 --- a/internal/calloc/CmdArgParser.go +++ b/internal/calloc/CmdArgParser.go @@ -40,6 +40,7 @@ var ( FlagGetUserEnv bool FlagExport string FlagExclusive bool + FlagMemPerCpu string FlagExtraAttr string FlagMailType string @@ -96,4 +97,6 @@ func init() { RootCmd.Flags().StringVar(&FlagComment, "comment", "", "Comment of the job") RootCmd.Flags().StringVarP(&FlagReservation, "reservation", "r", "", "Use reserved resources") RootCmd.Flags().BoolVar(&FlagExclusive, "exclusive", false, "Exclusive node resources") + RootCmd.Flags().StringVarP(&FlagMemPerCpu, "mem-per-cpu", "", "", "Maximum amount of real memory per CPU, support GB(G, g), MB(M, m), KB(K, k) and Bytes(B), default unit is MB") + RootCmd.MarkFlagsMutuallyExclusive("mem", "mem-per-cpu") } diff --git a/internal/calloc/calloc.go b/internal/calloc/calloc.go index 2044d95d..24e481d3 100644 --- a/internal/calloc/calloc.go +++ b/internal/calloc/calloc.go @@ -440,6 +440,16 @@ func MainCalloc(cmd *cobra.Command, args []string) error { task.ReqResources.AllocatableRes.MemoryLimitBytes = memInByte task.ReqResources.AllocatableRes.MemorySwLimitBytes = memInByte } + if FlagMemPerCpu != "" { + memInBytePerCpu, err := util.ParseMemStringAsByte(FlagMemPerCpu) + if err != nil { + return &util.CraneError{ + Code: util.ErrorCmdArg, + Message: fmt.Sprintf("Invalid argument: %v", err), + } + } + task.MemPerCpu = &memInBytePerCpu + } if FlagPartition != "" { task.PartitionName = FlagPartition } diff --git a/internal/cbatch/CmdArgParser.go b/internal/cbatch/CmdArgParser.go index 015f2067..d43382f1 100644 --- a/internal/cbatch/CmdArgParser.go +++ b/internal/cbatch/CmdArgParser.go @@ -49,6 +49,7 @@ var ( FlagStderrPath string FlagOpenMode string FlagExclusive bool + FlagMemPerCpu string FlagWrappedScript string @@ -163,4 +164,6 @@ func init() { RootCmd.Flags().StringVar(&FlagOpenMode, "open-mode", "", "Set the mode for opening output and error files, supported values: append, truncate (default is truncate) ") RootCmd.Flags().StringVarP(&FlagReservation, "reservation", "r", "", "Use reserved resources") RootCmd.Flags().BoolVar(&FlagExclusive, "exclusive", false, "Exclusive node resources") + RootCmd.Flags().StringVarP(&FlagMemPerCpu, "mem-per-cpu", "", "", "Maximum amount of real memory per CPU, support GB(G, g), MB(M, m), KB(K, k) and Bytes(B), default unit is MB") + RootCmd.MarkFlagsMutuallyExclusive("mem", "mem-per-cpu") } diff --git a/internal/cbatch/cbatch.go b/internal/cbatch/cbatch.go index a7ba7817..163fe9f0 100644 --- a/internal/cbatch/cbatch.go +++ b/internal/cbatch/cbatch.go @@ -105,6 +105,13 @@ func ProcessCbatchArgs(cmd *cobra.Command, args []CbatchArg) (bool, *protos.Task } task.ReqResources.AllocatableRes.MemoryLimitBytes = memInByte task.ReqResources.AllocatableRes.MemorySwLimitBytes = memInByte + case "--mem-per-cpu": + memInBytePerCpu, err := util.ParseMemStringAsByte(arg.val) + if err != nil { + log.Errorf("Invalid argument: %v in script: %v", arg.name, err) + return false, nil + } + task.MemPerCpu = &memInBytePerCpu case "-p", "--partition": task.PartitionName = arg.val case "-J", "--job-name": @@ -208,7 +215,14 @@ func ProcessCbatchArgs(cmd *cobra.Command, args []CbatchArg) (bool, *protos.Task task.ReqResources.AllocatableRes.MemoryLimitBytes = memInByte task.ReqResources.AllocatableRes.MemorySwLimitBytes = memInByte } - + if FlagMemPerCpu != "" { + memInBytePerCpu, err := util.ParseMemStringAsByte(FlagMemPerCpu) + if err != nil { + log.Errorf("Invalid argument: %v", err) + return false, nil + } + task.MemPerCpu = &memInBytePerCpu + } if FlagPartition != "" { task.PartitionName = FlagPartition } diff --git a/internal/crun/CmdArgParser.go b/internal/crun/CmdArgParser.go index 840dc288..bd95052c 100644 --- a/internal/crun/CmdArgParser.go +++ b/internal/crun/CmdArgParser.go @@ -41,6 +41,7 @@ var ( FlagGres string FlagPty bool FlagExclusive bool + FlagMemPerCpu string FlagX11 bool FlagX11Fwd bool @@ -107,4 +108,6 @@ func init() { RootCmd.Flags().StringVar(&FlagComment, "comment", "", "Comment of the job") RootCmd.Flags().StringVarP(&FlagReservation, "reservation", "r", "", "Use reserved resources") RootCmd.Flags().BoolVar(&FlagExclusive, "exclusive", false, "Exclusive node resources") + RootCmd.Flags().StringVarP(&FlagMemPerCpu, "mem-per-cpu", "", "", "Maximum amount of real memory per CPU, support GB(G, g), MB(M, m), KB(K, k) and Bytes(B), default unit is MB") + RootCmd.MarkFlagsMutuallyExclusive("mem", "mem-per-cpu") } diff --git a/internal/crun/crun.go b/internal/crun/crun.go index e62ac4f0..8fda881a 100644 --- a/internal/crun/crun.go +++ b/internal/crun/crun.go @@ -862,6 +862,16 @@ func MainCrun(args []string) error { task.ReqResources.AllocatableRes.MemoryLimitBytes = memInByte task.ReqResources.AllocatableRes.MemorySwLimitBytes = memInByte } + if FlagMemPerCpu != "" { + memInBytePerCpu, err := util.ParseMemStringAsByte(FlagMemPerCpu) + if err != nil { + return &util.CraneError{ + Code: util.ErrorCmdArg, + Message: fmt.Sprintf("Invalid argument: %v.", err), + } + } + task.MemPerCpu = &memInBytePerCpu + } if FlagGres != "" { gresMap := util.ParseGres(FlagGres) task.ReqResources.DeviceMap = gresMap diff --git a/protos/PublicDefs.proto b/protos/PublicDefs.proto index c9cda21e..46409dec 100644 --- a/protos/PublicDefs.proto +++ b/protos/PublicDefs.proto @@ -164,6 +164,7 @@ message TaskToCtld { string reservation = 36; bool exclusive = 37; + optional uint64 mem_per_cpu = 38; } message TaskInEmbeddedDb {