Use OSS

更新时间:
复制 MD 格式

PAI products like Deep Learning Containers (DLC) and Data Science Workshop (DSW) let you mount a data source from Object Storage Service (OSS) to a specified path in a container using ossfs 2.0 or Alibaba Cloud E-MapReduce's JindoFuse. You can also read OSS data using the OSS Connector for AI/ML or the OSS SDK. Choose the data access method that best suits your use case.

Background

In AI development, source data is often stored in OSS and downloaded to a training environment for model development and training. However, this common practice presents several challenges:

  • Long download times for datasets can leave GPUs idle.

  • Data must be repeatedly downloaded for each training job.

  • Random data sampling requires downloading the entire dataset to each training node.

To address these issues, consider the following methods for reading OSS data:

Access method

Description

Use cases

JindoFuse

Mounts an OSS dataset to a specified path in a container using the JindoFuse component, enabling direct data reads and writes.

  • You want to access OSS data as if it were a local dataset, or your dataset is small enough to benefit from JindoFuse's local caching.

  • Your framework is not PyTorch.

  • You need to write data to OSS.

ossfs 2.0

ossfs 2.0 is a client for high-performance mounted access to OSS. It excels at sequential read and write operations, enabling you to fully leverage the high bandwidth of OSS.

ossfs 2.0 is suitable for scenarios that require high-performance storage access, such as AI training, inference, big data processing, autonomous driving, and other compute-intensive workloads. These workloads primarily involve sequential and random reads, sequential (append-only) writes, and do not require full POSIX semantics.

OSS Connector for AI/ML

PAI integrates the OSS Connector for AI/ML to stream files from OSS directly within PyTorch code, simplifying and accelerating data access. Key advantages include:

  • Streaming load: Eliminates the need to pre-download data to the training environment, saving GPU idle time and reducing costs.

  • Developer-friendly interface: Aligns with PyTorch Dataset usage patterns. It offers a better abstraction than the OSS SDK and is easier to customize and extend.

  • High-efficiency reads: Delivers higher data read performance than the OSS SDK for more efficient data loading.

Use this connector for non-mounted access to accelerate dataset reading for PyTorch training, especially when reading millions of small files or requiring high throughput.

OSS SDK

Streams data from OSS using the OSS SDK. It offers a flexible and efficient solution, significantly reducing data request times and improving training efficiency.

Use the OSS Python SDK or OSS Python API for temporary, non-mounted access to OSS data, or when your application logic determines when to access OSS.

JindoFuse

DLC and DSW allow you to use the JindoFuse component to mount an OSS dataset or an OSS path to a specified path in a container. This allows you to directly read from and write to data stored in OSS during the training process.

Mounting methods

DLC

When you create a distributed training (DLC) job, you can mount OSS data. The following two mount types are supported: For detailed configuration instructions, see Create a training job.

image

Mount type

Description

Datasets

Select a dataset of the OSS type and configure the Mount Path. For public datasets, only read-only mode is supported.

Directly Mount

Directly mount an OSS bucket path.

If you use a Lingjun intelligent computing resource quota with local caching enabled, you can turn on the Use Cache switch to enable caching.

DSW

When you create a DSW instance, you can mount OSS data. The following two mount types are supported: For detailed configuration instructions, see Create a DSW instance.

image

Mount type

Description

Dataset Mounting

Select a dataset of the OSS type and configure the Mount Path. When you use a public dataset, only read-only mode is supported.

Storage Path Mounting

Directly mount an OSS bucket path.

Default configuration limitations

If you leave the Advanced Configurations parameters empty, the default configuration is applied. The default configuration has the following limitations:

  • To accelerate OSS file reads, metadata (directory and file lists) is cached when OSS is mounted.

    In a distributed training, if multiple nodes attempt to create the same directory, the metadata cache can cause each node to attempt the creation. Only one node will succeed, and the others will report an error.

  • By default, the OSS MultiPart API is used to create files. The object becomes visible in OSS only after the write operations are complete.

  • Concurrent read and write operations on the same file are not supported.

  • Random write operations on files are not supported.

Common JindoFuse configurations

You can also customize JindoFuse parameters in the advanced configuration based on your use case.

This topic provides JindoFuse configuration suggestions for some common scenarios. These settings may not provide optimal performance for all workloads. For more flexible configuration options, see the JindoFuse User Guide.
  • Quick Read/write: ensures quick reads and writes. However, data inconsistency may occur during concurrent reads or writes. You can mount training data and models to the mount path of this mode. We recommend that you do not use the mount path of this mode as the working directory.

    {
      "fs.oss.download.thread.concurrency": "Twice the number of CPU cores",
      "fs.oss.upload.thread.concurrency": "Twice the number of CPU cores",
      "fs.jindo.args": "-oattr_timeout=3 -oentry_timeout=0 -onegative_timeout=0 -oauto_cache -ono_symlink"
    }
    
  • Incremental Read/Write: ensures data consistency during incremental writing. If original data is overwritten, data inconsistency may occur. The reading speed is slightly slow. You can use this mode to save the model weight files for training data.

    {
      "fs.oss.upload.thread.concurrency": "Twice the number of CPU cores",
      "fs.jindo.args": "-oattr_timeout=3 -oentry_timeout=0 -onegative_timeout=0 -oauto_cache -ono_symlink"
    }
    
  • Consistent Read/write: ensures data consistency during concurrent reads or writes and is suitable for scenarios that require high data consistency and do not require quick reads. You can use this mode to save the code of your projects.

    {
      "fs.jindo.args": "-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0 -oauto_cache -ono_symlink"
    }
    
  • Read-only: allows only reads. You can use this mode to mount public datasets.

    {
      "fs.oss.download.thread.concurrency": "Twice the number of CPU cores",
      "fs.jindo.args": "-oro -oattr_timeout=7200 -oentry_timeout=7200 -onegative_timeout=7200 -okernel_cache -ono_symlink"
    }

Other common configuration operations include:

  • Select a different JindoFuse version:

    {
      "fs.jindo.fuse.pod.image.tag": "6.7.0"
    }
  • Disable the metadata cache: When you run a distributed training where multiple nodes attempt to write to the same directory simultaneously, the cache might cause write operations on some nodes to fail. To resolve this issue, add the -oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0 argument to the JindoFuse command line.

    {
      "fs.jindo.args": "-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0"
    }
  • Adjust the upload/download thread count: Adjust the thread count by using the following parameters.

    {
      "fs.oss.upload.thread.concurrency": "32",
      "fs.oss.download.thread.concurrency": "32",
      "fs.oss.read.readahead.buffer.count": "64",
      "fs.oss.read.readahead.buffer.size": "4194304"
    }
  • Use AppendObject for writes: All files created locally on the mount are created as objects in OSS by calling the AppendObject API. The size of an object created by using AppendObject cannot exceed 5 GB. For more usage limits, see AppendObject. The following is a sample configuration:

    {
      "fs.jindo.args": "-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0",
      "fs.oss.append.enable": "true",
      "fs.oss.flush.interval.millisecond": "1000",
      "fs.oss.read.readahead.buffer.size": "4194304",
      "fs.oss.write.buffer.size": "262144"
    }
  • Mount OSS-HDFS: For information about how to enable OSS-HDFS, see What is OSS-HDFS service? In distributed training scenarios, we recommend that you add the following parameters:

    {
      "fs.jindo.args": "-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0 -ono_symlink -ono_xattr -ono_flock -odirect_io",
      "fs.oss.flush.interval.millisecond": "10000",
      "fs.oss.randomwrite.sync.interval.millisecond": "10000"
    }
  • Configure memory resources: You can set the fs.jindo.fuse.pod.mem.limit parameter to tune the memory limit. The following code provides an example:

    {
      "fs.jindo.fuse.pod.mem.limit": "10Gi"
    }

Use the Python SDK to modify JindoFuse parameters for a dataset

You can also use the Python SDK to modify JindoFuse parameters.

  1. Complete the following prerequisites.

    1. Install the SDK for AI Workspace.

      !pip install alibabacloud-aiworkspace20210204
    2. Configure environment variables. For more information, see Install the Credentials Tool and Configure environment variables on Linux, macOS, and Windows.

  2. Modify the JindoFuse parameters.

    Fast read/write

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def change_config():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
        # Recommended value: twice the number of CPU cores.
        options['fs.oss.download.thread.concurrency'] = 32
        options['fs.oss.upload.thread.concurrency'] = 32
        options['fs.jindo.args'] = '-oattr_timeout=3 -oentry_timeout=0 -onegative_timeout=0 -oauto_cache -ono_symlink'
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    change_config()

    Incremental read/write

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def change_config():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
        # Recommended value: twice the number of CPU cores.
        options['fs.oss.upload.thread.concurrency'] = 32
        options['fs.jindo.args'] = '-oattr_timeout=3 -oentry_timeout=0 -onegative_timeout=0 -oauto_cache -ono_symlink'
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    change_config()

    Consistent read/write

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def change_config():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
        options['fs.jindo.args'] = '-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0 -oauto_cache -ono_symlink'
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    change_config()

    Read-only

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def change_config():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
        # Recommended value: twice the number of CPU cores.
        options['fs.oss.download.thread.concurrency'] = 32
        options['fs.jindo.args'] = '-oro -oattr_timeout=7200 -oentry_timeout=7200 -onegative_timeout=7200 -okernel_cache -ono_symlink'
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    change_config()

    JindoFuse version

    The following code provides an example:

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def change_version():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
        # Set the JindoFuse version. Supported versions include 6.4.4, 6.7.0, and 6.6.0. For release notes, see https://aliyun.github.io/alibabacloud-jindodata/releases/.
        options['fs.jindo.fuse.pod.image.tag'] = "6.7.0"
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    change_version()

    Metadata cache

    When you run a distributed training and multiple nodes attempt to write to the same directory simultaneously, the cache might cause write operations on some nodes to fail. To resolve this issue, add the -oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0 argument to the JindoFuse command line. The following code provides an example:

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def turnOffMetaCache():
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
        workspace_client = AIWorkspaceClient(
          config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
          )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
    
        options['fs.jindo.args'] = '-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0'
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    turnOffMetaCache()
    

    Upload/download thread count

    Set the following parameters to tune the thread count:

    • fs.oss.upload.thread.concurrency:32

    • fs.oss.download.thread.concurrency:32

    • fs.oss.read.readahead.buffer.count:64

    • fs.oss.read.readahead.buffer.size:4194304

    The following code provides an example:

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def adjustThreadNum():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
    
        options['fs.oss.upload.thread.concurrency'] = 32
        options['fs.oss.download.thread.concurrency'] = 32
        options['fs.oss.read.readahead.buffer.count'] = 64
     
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
     
     
    adjustThreadNum()
    

    AppendObject writes

    All files created locally on the mount are created as objects in OSS by calling the AppendObject API. The size of an object created by using AppendObject cannot exceed 5 GB. For more usage limits, see AppendObject. The following code provides an example:

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def useAppendObject():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
    
        options['fs.jindo.args'] = '-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0'
        options['fs.oss.append.enable'] = "true"
        options['fs.oss.flush.interval.millisecond'] = "1000"
        options['fs.oss.read.buffer.size'] = "262144"
        options['fs.oss.write.buffer.size'] = "262144"
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    useAppendObject()

    OSS-HDFS

    For information about how to enable OSS-HDFS, see What is OSS-HDFS service?. The following example shows how to create a dataset that uses an OSS-HDFS endpoint:

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import CreateDatasetRequest
    
    
    def createOssHdfsDataset():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        workspace_id = 'YOUR_WORKSPACE_ID'
    
        oss_bucket = 'YOUR_OSS_BUCKET'
        # Use the OSS-HDFS endpoint.
        oss_endpoint = f'{region_id}.oss-dls.aliyuncs.com'
        # The OSS-HDFS path to mount.
        oss_path = '/'
        # The local mount path.
        mount_path = '/mnt/data/'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
    
        response = workspace_client.create_dataset(CreateDatasetRequest(
            workspace_id=workspace_id,
            name="YOUR_DATASET_NAME",
            data_type='COMMON',
            data_source_type='OSS',
            property='DIRECTORY',
            uri=f'oss://{oss_bucket}.{oss_endpoint}{oss_path}',
            accessibility='PRIVATE',
            source_type='USER',
            options=json.dumps({
                'mountPath': mount_path,
                # In distributed training scenarios, we recommend that you add the following parameters.
                'fs.jindo.args': '-oattr_timeout=0 -oentry_timeout=0 -onegative_timeout=0 -ono_symlink -ono_xattr -ono_flock -odirect_io',
                'fs.oss.flush.interval.millisecond': "10000",
                'fs.oss.randomwrite.sync.interval.millisecond': "10000",
            })
        ))
        print(f'datasetId: {response.body.dataset_id}')
    
    createOssHdfsDataset()
    
    

    Memory resources

    You can set the fs.jindo.fuse.pod.mem.limit parameter to adjust the memory limit. The following code provides an example:

    import json
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
    from alibabacloud_aiworkspace20210204.models import UpdateDatasetRequest
    
    
    def adjustResource():
        # Use the region where the DLC job runs. For example, use cn-hangzhou for China (Hangzhou).
        region_id = 'cn-hangzhou'
        # An Alibaba Cloud account AccessKey has permissions to call all APIs. We recommend that you use a RAM user for API calls and daily O&M.
        # We strongly recommend that you do not store the AccessKey ID or AccessKey Secret in your code. Otherwise, your AccessKey may be leaked and put all resources in your account at risk.
        # In this example, the Credentials SDK reads the AccessKey from environment variables by default for authentication. You must install the Credentials tool and configure environment variables first.
        cred = CredClient()
        dataset_id = 'YOUR_DATASET_ID'
    
        workspace_client = AIWorkspaceClient(
            config=Config(
                credential=cred,
                region_id=region_id,
                endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
            )
        )
        # 1. Get the dataset content.
        get_dataset_resp = workspace_client.get_dataset(dataset_id)
        options = json.loads(get_dataset_resp.body.options)
        # The memory resource to configure.
        options['fs.jindo.fuse.pod.mem.limit'] = "10Gi"
    
        update_request = UpdateDatasetRequest(
            options=json.dumps(options)
        )
        # 2. Update the options.
        workspace_client.update_dataset(dataset_id, update_request)
        print('new options is: {}'.format(update_request.options))
    
    
    adjustResource()
    

ossfs 2.0

To mount an OSS data source using ossfs, set {"mountType":"ossfs"} in Advanced Configuration.

Mounting methods

Mount OSS in DLC

When you create a DLC job, you can mount OSS data. DLC supports the following two mount types. For configuration details, see Create a training job.

image

Mount type

Description

Datasets

Select an OSS dataset and configure the Mount Path. Public datasets support only read-only mode.

Directly Mount

Directly mount an OSS bucket storage path.

If you are using a Lingjun resource quota with local caching enabled, you can turn on Use Cache.

Mount OSS in DSW

When you create a DSW instance, you can mount OSS data. DSW supports the following two mount types. For configuration details, see Create a DSW instance.

image

Mount type

Description

Dataset Mounting

Select an OSS dataset and configure the Mount Path. Public datasets support only read-only mode.

Storage Path Mounting

Directly mount an OSS bucket storage path.

Common ossfs configurations

In Advanced Configuration, you can set advanced parameters using fs.ossfs.args. Separate multiple parameters with a comma (,). For more information about these advanced parameters, see ossfs 2.0. The following examples show several common use cases:

  • Static data source during the job: For files that are not modified during the job, configure a long cache timeout to reduce metadata requests. A typical use case is reading a batch of existing files and generating a new set of files after processing.

    {
        "mountType":"ossfs",
        "fs.ossfs.args": "-oattr_timeout=7200" 
    }
  • Fast read/write: Use a shorter metadata cache timeout to balance cache efficiency and data freshness.

    {
        "mountType":"ossfs",
        "fs.ossfs.args": "-oattr_timeout=3, -onegative_timeout=0"
    }
  • Consistent read/write for distributed jobs: By default, ossfs updates file data based on the metadata cache. Use the following configuration to ensure a consistent view across multiple nodes.

    {   
        "mountType":"ossfs",
        "fs.ossfs.args": "-onegative_timeout=0, -oclose_to_open"
    }
  • Out-of-memory (OOM) from too many open files in DLC or DSW: High job concurrency in DLC and DSW can open many files simultaneously, potentially causing Out-of-memory (OOM) issues. The following configuration can help reduce memory pressure.

    {
        "mountType":"ossfs",
        "fs.ossfs.args": "-oreaddirplus=false, -oinode_cache_eviction_threshold=300000"
    }
  • Failure to write large files: -oupload_buffer_size sets the buffer size (in bytes) for multipart uploads. This parameter determines the maximum writable file size, calculated as upload_buffer_size * 10000.

    By default, ossfs 2.0 uses a part size of 8 MiB, which limits the maximum writable file size to 78.125 GiB. When you write a file that exceeds this limit, the operation fails. To increase the maximum supported file size, configure the -oupload_buffer_size option to increase the part size. For example, setting the part size to 32 MiB (33,554,432 bytes) supports a maximum file size of 312.5 GiB. Note that a larger -upload_buffer_size consumes more memory. You can control memory usage by configuring -total_mem_limit. For more information, see Mount options.

    {
        "mountType":"ossfs",
        "fs.ossfs.args": "-oupload_buffer_size=33554432"
    }
    

OSS Connector for AI/ML

The OSS Connector for AI/ML is a client library from the Alibaba Cloud OSS team for AI and machine learning workloads. It simplifies data loading for large-scale PyTorch training, reduces data transfer time and complexity, and accelerates model training by eliminating data loading bottlenecks. To streamline data access, the PAI platform has integrated the OSS Connector for AI/ML, allowing you to stream data directly from OSS within your PyTorch code for efficient data loading.

Limitations

  • Official images: The OSS Connector for AI/ML is available only in DLC jobs and DSW instances that use an official image of PyTorch 2.0 or later.

  • Custom images: Only PyTorch 2.0 or later is supported. For custom images that use a supported version, install the OSS Connector for AI/ML by running the following command:

    pip install -i http://yum.tbsite.net/aliyun-pypi/simple/ --extra-index-url http://yum.tbsite.net/pypi/simple/ --trusted-host=yum.tbsite.net osstorchconnector
  • Python version: Only Python 3.8–3.12 is supported.

Prerequisites

  1. Configure a credential file.

    You can configure credentials in one of the following ways:

    • Configure password-free access to OSS for your DLC job. For more information, see Configure a DLC RAM role. With this method, the DLC job obtains a temporary credential from STS to securely access OSS and other cloud resources, eliminating the need for explicit authentication information and reducing the risk of access key leakage.

    • Configure a credential file in your code project to manage authentication information. The following code provides a sample configuration:

      Note

      Storing access key information in plaintext poses a security risk. We recommend using a RAM role to automatically configure credentials within a DLC instance. For more information, see Configure a DLC RAM role.

      When you use the OSS Connector for AI/ML, you can specify the path to the credential file to automatically retrieve authentication information for signing OSS data requests.

      {
        "AccessKeyId": "<Access-key-id>",
        "AccessKeySecret": "<Access-key-secret>",
        "SecurityToken": "<Security-Token>",
        "Expiration": "2024-08-20T00:00:00Z"
      }

      The following table describes the fields.

      Parameter

      Required

      Description

      Example

      AccessKeyId

      Yes

      The access key ID and access key secret of an Alibaba Cloud account or a RAM user.

      Note

      When you use a temporary credential from STS to access OSS, set these parameters to the temporary access key ID and access key secret.

      NTS****

      AccessKeySecret

      Yes

      7NR2****

      SecurityToken

      No

      The security token from STS. This parameter is required only when you use a temporary credential from STS to access OSS.

      STS.6MC2****

      Expiration

      No

      The credential's expiration time. If this field is empty, the credential does not expire. The OSS Connector for AI/ML re-reads the credential file when the credential expires.

      2024-08-20T00:00:00Z

  2. Configure a config.json file. The following code provides a sample configuration:

    This file is used to manage settings in your project, such as concurrency levels, prefetch parameters, and log file locations. When using the OSS Connector for AI/ML, specify the path to this config.json file. The connector then automatically applies your configured settings and writes logs related to OSS data requests to the specified log file.

    {
        "logLevel": 1,
        "logPath": "/var/log/oss-connector/connector.log",
        "auditPath": "/var/log/oss-connector/audit.log",
        "datasetConfig": {
            "prefetchConcurrency": 24,
            "prefetchWorker": 2
        },
        "checkpointConfig": {
            "prefetchConcurrency": 24,
            "prefetchWorker": 4,
            "uploadConcurrency": 64
        }
    }

    The following table describes the fields.

    Parameter

    Required

    Description

    Example

    logLevel

    Yes

    The log level. The default value is 1 (INFO). Valid values:

    • 0: DEBUG

    • 1: INFO

    • 2: WARN

    • 3: ERROR

    1

    logPath

    Yes

    The log path for the connector. The default path is /var/log/oss-connector/connector.log.

    /var/log/oss-connector/connector.log

    auditPath

    Yes

    The audit log for Connector I/O records read and write requests with a latency greater than 100 milliseconds. The default path is /var/log/oss-connector/audit.log.

    /var/log/oss-connector/audit.log

    DatasetConfig

    prefetchConcurrency

    Yes

    The number of concurrent tasks for prefetching data from OSS when using a dataset. The default value is 24.

    24

    prefetchWorker

    Yes

    The number of vCPUs available for prefetching data from OSS when using a dataset. The default value is 2.

    2

    checkpointConfig

    prefetchConcurrency

    Yes

    The number of concurrent tasks for prefetching data from OSS during a checkpoint read. The default value is 24.

    24

    prefetchWorker

    Yes

    The number of vCPUs available for prefetching data from OSS during a checkpoint read. The default value is 4.

    4

    uploadConcurrency

    Yes

    The number of concurrent tasks for uploading data during a checkpoint write. The default value is 64.

    64

Usage

The OSS Connector for AI/ML provides two dataset access interfaces, OssMapDataset and OssIterableDataset, which extend PyTorch's Dataset and IterableDataset interfaces, respectively. OssIterableDataset is optimized with prefetching for higher training efficiency. The data reading order of OssMapDataset is determined by the DataLoader and supports shuffle operations. You can choose a dataset access interface based on the following recommendations:

  • If you have limited memory, a large dataset, and require only sequential reads with low parallelism, use OssIterableDataset.

  • If you have sufficient memory, a smaller dataset, and require random access and parallel processing, use OssMapDataset.

The OSS Connector for AI/ML also provides the OssCheckpoint interface for loading and saving models. Currently, the OssCheckpoint feature is available only in general-purpose computing resource environments.

The following sections describe how to use these three interfaces.

OssMapDataset

The following three dataset access methods are supported:

  • Access a folder by OSS path prefix

    You can specify just the folder name without needing to configure an index file, which simplifies maintenance and scalability. Use this method if your OSS folder is structured as follows:

    dataset_folder/
        ├── class1/
        │   ├── image1.JPEG
        │   └── ...
        ├── class2/
        │   ├── image2.JPEG
        │   └── ...

    When you use this method, you must specify an OSS path prefix and define a custom method to parse the file stream. The following example shows how to parse and transform image files:

    def read_and_transform(data):
        normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                         std=[0.229, 0.224, 0.225])
        transform = transforms.Compose([
            transforms.RandomResizedCrop(224),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            normalize,
        ])
    
        try:
            img = accimage.Image((data.read()))
            val = transform(img)
            label = data.label # File name
        except Exception as e:
            print("read failed", e)
            return None, 0
        return val, label
    dataset = OssMapDataset.from_prefix("{oss_data_folder_uri}", endpoint="{oss_endpoint}", transform=read_and_transform, cred_path=cred_path, config_path=config_path)
  • Access files from a manifest file

    This method allows you to access data from multiple OSS buckets, providing more flexible data management. Use this method if your OSS folder is structured as follows and you have a manifest file that maps filenames to labels.

    dataset_folder/
        ├── class1/
        │   ├── image1.JPEG
        │   └── ...
        ├── class2/
        │   ├── image2.JPEG
        │   └── ...
        └── .manifest

    The manifest file has the following format:

    {'data': {'source': 'oss://examplebucket.oss-cn-wulanchabu.aliyuncs.com/dataset_folder/class1/image1.JPEG'}}
    {'data': {'source': ''}}

    When you use this method, you must define a custom method to parse the manifest file. The following code provides an example:

    def transform_oss_path(input_path):
        pattern = r'oss://(.*?)\.(.*?)/(.*)'
        match = re.match(pattern, input_path)
        if match:
            return f'oss://{match.group(1)}/{match.group(3)}'
        else:
            return input_path
    
    
    def manifest_parser(reader: io.IOBase) -> Iterable[Tuple[str, str, int]]:
        lines = reader.read().decode("utf-8").strip().split("\n")
        data_list = []
        for i, line in enumerate(lines):
            data = json.loads(line)
            yield transform_oss_path(data["data"]["source"]), ""
    dataset = OssMapDataset.from_manifest_file("{manifest_file_path}", manifest_parser, "", endpoint=endpoint, transform=read_and_trans, cred_path=cred_path, config_path=config_path)
  • Access files from a list of OSS URIs

    You can access OSS files by specifying their OSS URIs without needing to configure an index file. The following code provides an example:

    uris =["oss://examplebucket.oss-cn-wulanchabu.aliyuncs.com/dataset_folder/class1/image1.JPEG", "oss://examplebucket.oss-cn-wulanchabu.aliyuncs.com/dataset_folder/class2/image2.JPEG"]
    dataset = OssMapDataset.from_objects(uris, endpoint=endpoint, transform=read_and_trans, cred_path=cred_path, config_path=config_path)

OssIterableDataset

OssIterableDataset supports the same three dataset access methods as OssMapDataset. The following examples show how to use these three methods:

  • Access a folder by OSS path prefix

    dataset = OssIterableDataset.from_prefix("{oss_data_folder_uri}", endpoint="{oss_endpoint}", transform=read_and_transform, cred_path=cred_path, config_path=config_path)
  • Access files from a manifest file

    dataset = OssIterableDataset.from_manifest_file("{manifest_file_path}", manifest_parser, "", endpoint=endpoint, transform=read_and_trans, cred_path=cred_path, config_path=config_path)
  • Access files from a list of OSS URIs

    dataset = OssIterableDataset.from_objects(uris, endpoint=endpoint, transform=read_and_trans, cred_path=cred_path, config_path=config_path)

OssCheckpoint

Currently, the OssCheckpoint feature is available only in general-purpose computing resource environments. You can use the OssCheckpoint interface to access and save model files in OSS. The following code shows how to use the interface:

checkpoint = OssCheckpoint(endpoint="{oss_endpoint}", cred_path=cred_path, config_path=config_path)

checkpoint_read_uri = "{checkpoint_path}"
checkpoint_write_uri = "{checkpoint_path}"
with checkpoint.reader(checkpoint_read_uri) as reader:
    state_dict = torch.load(reader)
    model.load_state_dict(state_dict)
with checkpoint.writer(checkpoint_write_uri) as writer:
    torch.save(model.state_dict(), writer)

Code example

The following code provides a full example of how to use the OSS Connector for AI/ML to access OSS data:

from osstorchconnector import OssMapDataset, OssCheckpoint
import torchvision.transforms as transforms
import accimage
import torchvision.models as models
import torch

# The default credential path after you configure a RAM role for a DLC job or DSW instance.
cred_path = "/mnt/.alibabacloud/credentials"  
config_path = "config.json"
checkpoint = OssCheckpoint(endpoint="{oss_endpoint}", cred_path=cred_path, config_path=config_path)
model = models.__dict__["resnet18"]()

epochs = 100  # Specify the number of epochs.
checkpoint_read_uri = "{checkpoint_path}"
checkpoint_write_uri = "{checkpoint_path}"
with checkpoint.reader(checkpoint_read_uri) as reader:
    state_dict = torch.load(reader)
    model.load_state_dict(state_dict)


def read_and_transform(data):
    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
    transform = transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        normalize,
    ])

    try:
        img = accimage.Image((data.read()))
        value = transform(img)
    except Exception as e:
        print("read failed", e)
        return None, 0
    return value, 0
dataset = OssMapDataset.from_prefix("{oss_data_folder_uri}", endpoint="{oss_endpoint}", transform=read_and_transform, cred_path=cred_path, config_path=config_path)
data_loader = torch.utils.data.DataLoader(
    dataset, batch_size="{batch_size}",num_workers="{num_workers"}, pin_memory=True)

for epoch in range(args.epochs):
    for step, (images, target) in enumerate(data_loader):
        # batch processing
        # model training
    # save model
    with checkpoint.writer(checkpoint_write_uri) as writer:
        torch.save(model.state_dict(), writer)

Key points in this example:

  • Build a dataset with OssMapDataset directly from the given OSS URI, following the standard PyTorch DataLoader pattern.

  • Use this dataset to create a standard PyTorch DataLoader, and run a normal training loop to process each batch, train the model, and save checkpoints.

  • This enables on-demand loading, which eliminates the need to mount the dataset in the container environment or download it to local storage beforehand.

OSS SDK

OSS Python SDK

Use the OSS Python SDK to read data from and write data to OSS:

  1. Install the OSS Python SDK. For more information, see Installation (Python SDK V1).

  2. Configure access credentials for the OSS Python SDK. For more information, see Configure access credentials (Python SDK V1).

  3. Read and write data in OSS.

    # -*- coding: utf-8 -*-
    import oss2
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    
    # Configure access credentials using the RAM user access key from environment variables.
    auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
    bucket = oss2.Bucket(auth, '<Endpoint>', '<your_bucket_name>')
    # Read a complete file.
    result = bucket.get_object('<your_file_path/your_file>')
    print(result.read())
    # Read data by range.
    result = bucket.get_object('<your_file_path/your_file>', byte_range=(0, 99))
    # Write data to OSS.
    bucket.put_object('<your_file_path/your_file>', '<your_object_content>')
    # Append data to an appendable file.
    result = bucket.append_object('<your_file_path/your_file>', 0, '<your_object_content>')
    result = bucket.append_object('<your_file_path/your_file>', result.next_position, '<your_object_content>')
    

    Modify the following parameters as needed:

    Parameter

    Description

    <Endpoint>

    The endpoint for your bucket's region. For example, for the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. For more information about how to obtain an endpoint, see Regions and endpoints.

    <your_bucket_name>

    The name of your bucket.

    <your_file_path/your_file>

    The path of the file to read or write. Specify the full path of the object but exclude the bucket name. For example, testfolder/exampleobject.txt.

    <your_object_content>

    The content to write or append. Replace as needed.

OSS Python API

You can use the OSS Python API to conveniently store training data and models in OSS. Before you begin, ensure you have installed the OSS Python SDK and configured your access credentials. For more information, see Installation (Python SDK V1) and Configure access credentials (Python SDK V1).

  • Load training data

    You can store your data in an OSS bucket, with the data paths and corresponding labels in an index file in the same bucket. By creating a custom Dataset, you can use the DataLoader API in PyTorch to read data in parallel across multiple processes. The following code is an example.

    import io
    import oss2
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    import PIL
    import torch
    
    class OSSDataset(torch.utils.data.dataset.Dataset):
        def __init__(self, endpoint, bucket, auth, index_file):
            self._bucket = oss2.Bucket(auth, endpoint, bucket)
            self._indices = self._bucket.get_object(index_file).read().split(',')
    
        def __len__(self):
            return len(self._indices)
    
        def __getitem__(self, index):
            img_path, label = self._indices(index).strip().split(':')
            img_str = self._bucket.get_object(img_path)
            img_buf = io.BytesIO()
            img_buf.write(img_str.read())
            img_buf.seek(0)
            img = Image.open(img_buf).convert('RGB')
            img_buf.close()
            return img, label
    
    
    # Obtain access credentials from environment variables. Before you run this code sample,
    # make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
    auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
    dataset = OSSDataset(endpoint, bucket, auth, index_file)
    data_loader = torch.utils.data.DataLoader(
        dataset,
        batch_size=batch_size,
        num_workers=num_loaders,
        pin_memory=True)
    

    This table describes the key parameters.

    Parameter

    Description

    endpoint

    The endpoint for your bucket's region. For example, for the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. For more information about how to obtain an endpoint, see Regions and endpoints.

    bucket

    The name of your bucket.

    index_file

    The path of the index file.

    Note

    In the example, the index file uses a comma (,) to separate each sample, and a colon (:) to separate the sample path from the label.

  • Save or load models

    Use the OSS Python API to save or load PyTorch models. For more information about how to save and load models in PyTorch, see PyTorch. The following code provides examples:

    • Save a model

      from io import BytesIO
      import torch
      import oss2
      from oss2.credentials import EnvironmentVariableCredentialsProvider
      
      auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
      # bucket_name
      bucket_name = "<your_bucket_name>"
      bucket = oss2.Bucket(auth, endpoint, bucket_name)
      buffer = BytesIO()
      torch.save(model.state_dict(), buffer)
      bucket.put_object("<your_model_path>", buffer.getvalue())
      

      Where:

      • endpoint is the endpoint for your bucket's region. For example, for the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.

      • <your_bucket_name> is the name of the OSS bucket, without the oss:// prefix.

      • <your_model_path> is the model path. Replace it as needed.

    • Load a model

      from io import BytesIO
      import torch
      import oss2
      from oss2.credentials import EnvironmentVariableCredentialsProvider
      
      auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
      bucket_name = "<your_bucket_name>"
      bucket = oss2.Bucket(auth, endpoint, bucket_name)
      buffer = BytesIO(bucket.get_object("<your_model_path>").read())
      model.load_state_dict(torch.load(buffer))

      Where:

      • endpoint is the endpoint for your bucket's region. For example, for the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.

      • <your_bucket_name> is the name of the OSS bucket, without the oss:// prefix.

      • <your_model_path> is the model path. Replace it as needed.