Section 1: Why Machine Learning Models Must Be Designed Around Hardware Constraints
Understanding the Difference Between Theoretical Computation and Actual Runtime Performance
Machine learning engineers frequently evaluate model efficiency through metrics such as parameter count, floating-point operations, and computational complexity, but these measurements do not fully explain how a model will perform on the hardware used for training or inference. A model with fewer parameters or fewer arithmetic operations may still execute more slowly than a larger alternative if its operations are poorly matched to the processor, require frequent memory transfers, or prevent efficient parallel execution. Hardware-aware machine learning addresses this gap by considering the interaction between model architecture, software runtime, and physical computing resources when designing models for real deployment environments.
Consider two neural networks that perform the same classification task, with one using a relatively compact architecture and the other using larger matrix operations that are better suited to the available accelerator. Although the compact model may require fewer theoretical computations, the larger model could achieve lower inference latency if its operations map more efficiently to optimized hardware kernels and make better use of parallel processing units. Conversely, a theoretically efficient architecture may perform poorly on a particular device when its operators require unsupported execution paths or introduce substantial data movement, demonstrating why complexity metrics alone are insufficient for choosing a production model.
Engineers should therefore measure actual execution time, throughput, memory consumption, and energy usage on representative workloads rather than relying exclusively on theoretical estimates. These measurements reveal how the combined effects of model structure, runtime implementation, and hardware capabilities determine practical performance, while the principles discussed in “Resource-Aware Machine Learning: Designing Models Around Compute and Energy Limits” provide useful context for designing ML systems around real computational constraints. By incorporating hardware performance into model selection from the beginning, teams can avoid optimizing architectures that look efficient in development but become expensive or slow after deployment.
How Compute Throughput, Memory Bandwidth, and Data Movement Shape Model Execution
Model execution depends on more than the number of arithmetic operations performed because processors must also move model parameters, intermediate activations, and input data through different levels of the memory hierarchy. Compute throughput describes how quickly a device can perform supported operations, while memory bandwidth determines how quickly data can be transferred between memory and processing units, making the relationship between computation and data movement an important factor in actual inference performance. When an operation requires substantial memory access relative to the computation it performs, the model may become memory-bound, leaving some computational capacity unused while the hardware waits for data.
This distinction becomes particularly important for models that contain large embedding tables, repeated tensor transformations, or workloads involving substantial intermediate data. An operation with relatively few arithmetic calculations can still become a bottleneck if it repeatedly retrieves values from memory, while a computationally intensive matrix multiplication may execute efficiently on a GPU because the hardware can process many operations in parallel once the required data is available. Engineers should therefore consider both computation and memory traffic when evaluating model architectures, particularly when deploying models on devices with limited memory bandwidth or constrained memory capacity.
Data movement can also consume significant energy and add latency, especially when information must travel between host memory and accelerator memory or between multiple processing components. Optimizations such as reducing intermediate tensor sizes, reusing data, selecting hardware-compatible operators, and minimizing unnecessary transfers can improve performance without requiring a fundamentally different model architecture. By profiling memory allocation, data-transfer time, operator execution, and hardware utilization together, engineering teams can determine whether a model is limited primarily by computational throughput or by the cost of moving data through the system.
Matching Model Requirements to CPUs, GPUs, Accelerators, and Edge Devices
Different hardware platforms offer different combinations of computational throughput, memory capacity, parallelism, energy efficiency, and software support, making hardware selection an important part of machine learning system design. CPUs provide flexible execution and can perform well for lightweight models, small workloads, and operations with limited parallelism, while GPUs are particularly useful for workloads containing large amounts of parallel numerical computation. Specialized AI accelerators may offer efficient execution for supported operations, but their usefulness depends on model compatibility, precision requirements, available memory, and the maturity of the software tools used to compile and execute the model.
Edge devices introduce different constraints because they may operate with limited power, restricted memory, thermal limits, or intermittent connectivity, making it impractical to deploy architectures designed exclusively for large server-class accelerators. A model intended for a mobile device, industrial sensor, or embedded system may need a smaller parameter footprint and lower computational demand to satisfy response-time and battery-life requirements, even when a larger model delivers better predictive performance in an unconstrained environment. Choosing an appropriate architecture therefore requires evaluating the complete deployment context rather than assuming that the most powerful available hardware is always the best option.
The model and hardware should be considered together because changing the target platform can alter which architecture offers the best balance between prediction quality and execution efficiency. Engineers may compare alternative layer configurations, numerical precision formats, operator implementations, and memory requirements against the capabilities of the intended device, using representative inference workloads to identify practical advantages and limitations. This approach also helps determine whether the primary constraint should be addressed through model redesign, runtime optimization, additional compute capacity, or a different deployment target, enabling teams to make hardware decisions based on measured requirements rather than theoretical peak performance alone.
Key Takeaway
Hardware-aware machine learning treats model architecture and computing hardware as interconnected design decisions, recognizing that theoretical operation counts and parameter sizes do not fully predict real execution performance. By considering compute throughput, memory bandwidth, data movement, hardware compatibility, and workload-specific requirements, engineering teams can select and optimize models for the devices that will actually execute them. The objective is to balance prediction quality with latency, throughput, memory consumption, and energy efficiency through empirical benchmarking and deliberate hardware–software co-design.
Section 2: Designing Model Architectures That Match Their Target Hardware
Choosing Model Depth, Width, and Computational Structure for Efficient Execution
Designing a machine learning model for a specific hardware platform requires engineers to consider how architectural decisions influence both predictive capability and computational efficiency, because the way a model organizes its operations can be just as important as the total number of operations it performs. Model depth determines how many sequential processing stages an input passes through, while model width influences the number of neurons, channels, or hidden dimensions processed within each stage, creating different trade-offs between representation capacity, memory requirements, and execution latency. Although increasing depth or width can improve a model's ability to represent complex relationships, these changes can also increase parameter storage, intermediate activation memory, and the amount of computation required for each prediction.
A deeper neural network may require several sequential operations before producing an output, limiting how much of its execution can occur simultaneously, whereas a wider network may expose more parallel computation at individual stages but demand greater memory bandwidth and accelerator capacity. The practical effect depends on the target hardware because some processors execute large matrix operations efficiently, while others handle smaller operations or lightweight inference workloads more economically. Engineers should therefore compare alternative architectures using representative input sizes and realistic runtime configurations, measuring latency, throughput, memory consumption, and prediction quality rather than assuming that a particular depth or width will always produce the best performance.
Architectural choices also involve selecting the kinds of operations used to process information, including dense matrix multiplication, convolutions, attention mechanisms, embedding lookups, and element-wise transformations, each of which interacts differently with the hardware and its execution libraries. A model that relies heavily on operations supported by optimized hardware kernels may outperform another model with fewer theoretical operations but less efficient execution patterns, making operator compatibility an important consideration during model design. By evaluating architectural structures alongside their intended runtime and compute platform, engineering teams can choose models that deliver the required predictive capability without introducing unnecessary computational overhead.
Understanding Matrix Operations, Parallelism, and Hardware Utilization
Many machine learning workloads rely on matrix multiplication and tensor operations that can be executed across numerous processing units, making parallelism a central factor in hardware-aware architecture design. GPUs and specialized accelerators can achieve high throughput when models expose sufficiently large, regular computational operations that map efficiently to their execution units, while workloads dominated by small operations or sequential dependencies may leave significant portions of the hardware underutilized. Engineers should therefore examine how the dimensions of model layers, tensor shapes, batch sizes, and operator sequences influence parallel execution, since architectural efficiency depends on how effectively the model's workload matches the hardware's computational organization.
Matrix dimensions can influence performance because hardware libraries often optimize particular shapes and numerical formats more effectively than others, allowing two architectures with similar theoretical operation counts to achieve different execution times. A model that uses dimensions compatible with optimized matrix kernels may execute efficiently, while an alternative architecture containing irregular tensor shapes or frequent small operations can introduce overhead from kernel launches, synchronization, and intermediate data movement. These effects become particularly important in low-latency inference, where the overhead associated with individual operations may contribute significantly to the total response time even when the amount of computation appears modest.
Hardware utilization also depends on whether the model provides enough independent work to keep the available processing units busy without exceeding memory capacity or creating excessive contention. Increasing batch size can improve parallel efficiency by allowing multiple inputs to be processed together, although the additional memory requirement and potential waiting time may make larger batches unsuitable for latency-sensitive applications. By benchmarking different batch sizes, tensor dimensions, operator implementations, and concurrency settings on the intended hardware, engineers can identify configurations that balance computational utilization with response time and resource consumption instead of relying exclusively on advertised peak performance.
Why Smaller Models Can Outperform Larger Models on Constrained Hardware
Smaller models can provide substantial advantages in production environments where memory capacity, processing power, energy consumption, or inference latency limits the feasible architectural choices. Reducing parameter count can lower model-storage requirements and may decrease the volume of data transferred during execution, while simpler computational structures can reduce intermediate memory allocations and initialization overhead. These advantages are particularly important for mobile applications, embedded systems, edge devices, and high-volume inference services, where the cost of repeatedly executing a model can matter more than the marginal accuracy improvement offered by a larger architecture.
However, a smaller parameter count does not automatically guarantee faster inference because actual performance depends on the operations performed, the efficiency of the runtime, and the capabilities of the target hardware. A compact model that relies on unsupported operations or irregular memory-access patterns may execute less efficiently than a somewhat larger model built around well-optimized matrix operations, while a heavily compressed architecture may introduce additional runtime overhead if its representation is not supported efficiently by the deployment platform. Engineers must therefore compare practical measurements rather than treating model size as a complete proxy for execution efficiency.
Model compression techniques such as pruning, quantization, and knowledge distillation can help reduce the cost of deploying capable models on constrained hardware, although each technique introduces trade-offs that require careful evaluation. Quantization reduces numerical precision to lower storage and computational requirements when supported effectively by the hardware, pruning removes selected parameters or structures when the resulting sparsity can be exploited by the execution runtime, and distillation trains a smaller model to reproduce useful behavior learned by a larger teacher model. The principles discussed in “Small Models, Big Impact: Why Compact ML Models Are Having a Comeback” are relevant because compact models can provide strong practical value when their architecture is aligned with the workload and deployment environment, allowing teams to reduce compute requirements without sacrificing more predictive performance than the application can tolerate.
Key Takeaway
Hardware-aware model design requires selecting architectural depth, width, computational operations, and numerical representations according to the capabilities and constraints of the target compute platform. Parallelism, memory bandwidth, operator support, and runtime overhead can produce substantial differences between theoretical complexity and measured performance, making empirical benchmarking essential when comparing model architectures. By evaluating compact models, hardware-compatible operations, and architecture-search candidates against explicit accuracy, latency, memory, and energy objectives, engineering teams can build models that use available compute more efficiently without compromising the application's essential requirements.
Section 3: Optimizing Models Through Quantization, Pruning, and Efficient Inference
Reducing Numerical Precision to Accelerate Model Computation
Hardware-aware machine learning often improves inference performance by reducing the numerical precision used to represent model parameters and intermediate computations, allowing compatible processors to execute certain operations with less memory traffic and greater computational throughput. Conventional neural networks frequently use 32-bit floating-point values during training or inference, but many deployment workloads can operate effectively with 16-bit floating-point formats, lower-precision integers, or other supported numerical representations. By reducing the number of bits required to store parameters and activations, engineers can decrease model memory requirements and potentially improve inference speed, particularly when the target hardware provides optimized execution support for the selected precision.
Quantization converts model values from a higher-precision representation into a lower-precision format, often using scaling factors and zero points to map numerical ranges into the available representable values. For example, an inference model quantized to 8-bit integers may require substantially less storage for its parameters than the same model represented with 32-bit floating-point values, while compatible hardware may execute the resulting operations more efficiently. However, the performance benefit depends on the processor, inference runtime, operator implementation, and quantization strategy, since unsupported operations or frequent conversions between numerical formats can reduce the advantages expected from lower precision.
Engineering teams can evaluate post-training quantization when an already trained model needs a more efficient deployment representation, while quantization-aware training may be appropriate when simulating reduced precision during training helps preserve accuracy. Both approaches require validation against representative inputs because numerical approximation can affect prediction quality, particularly for sensitive layers or models operating near important decision boundaries. The principles explored in “Quantization Explained: How AI Models Become Faster and Cheaper to Run” provide useful context for understanding how numerical precision influences model efficiency, while emphasizing the need to measure actual improvements on the hardware where inference will occur.
Using Pruning, Sparsity, and Distillation to Reduce Compute Requirements
Pruning reduces model complexity by removing selected parameters, connections, channels, or other structures that contribute relatively little to the model's behavior, potentially lowering storage requirements and the amount of computation needed during inference. Unstructured pruning removes individual weights, creating sparse parameter matrices, whereas structured pruning removes complete units such as channels or filters, producing smaller computational structures that conventional hardware may execute more efficiently. Although both methods can reduce the number of parameters retained in a model, the practical speedup depends on whether the inference runtime and target hardware can exploit the resulting sparsity without introducing excessive indexing, scheduling, or memory-access overhead.
Knowledge distillation offers another approach to producing efficient models by training a smaller student model to reproduce useful behavior learned by a larger teacher model. Instead of learning exclusively from hard target labels, the student can use the teacher's probability distributions or other training signals to capture richer information about relationships among classes or candidate outputs, potentially preserving much of the teacher's predictive capability with fewer parameters. This approach is particularly attractive when a large model provides valuable predictions but exceeds the latency, memory, or energy budget of the intended deployment platform, although the final performance depends on the quality of the training data, student architecture, and distillation objective.
Pruning and distillation should be evaluated as engineering trade-offs rather than assumed to produce automatic performance improvements, because a smaller parameter count does not necessarily translate into faster execution or lower end-to-end latency. A sparse model may require specialized kernels to exploit its reduced computation, while a distilled model may achieve efficient inference because its architecture is naturally compatible with the target processor. By comparing model size, measured latency, throughput, memory consumption, and prediction quality across these alternatives, engineering teams can determine whether compression improves practical efficiency instead of optimizing a theoretical measure that the deployment hardware cannot fully exploit.
Aligning Operators, Batch Sizes, and Execution Kernels With Hardware Capabilities
Even when a model's overall architecture is appropriate for a target device, its inference performance can be constrained by individual operators that execute inefficiently or require unnecessary data movement between processing stages. Operations such as matrix multiplication, convolution, normalization, attention, and element-wise transformations may have very different execution characteristics, making operator-level profiling useful for identifying which parts of the model consume the most time or memory bandwidth. Engineers can then select compatible implementations, simplify redundant operations, or adjust computational structures to better match the optimized kernels provided by the inference runtime and underlying hardware.
Batching can improve execution efficiency by allowing multiple inputs to share the overhead associated with model invocation and by increasing the amount of parallel work available to the processor. A service that processes large numbers of independent predictions may achieve higher throughput by evaluating requests in batches, while an interactive API with a strict response-time requirement may benefit more from immediate execution on small batches rather than waiting for additional requests to arrive. Batch configuration must therefore reflect the workload's latency and throughput objectives, since larger batches can increase memory use and improve hardware utilization while also adding waiting time or causing resource contention.
Inference runtimes and compilers can further optimize execution by fusing compatible operators, reducing intermediate tensor allocations, selecting optimized kernels, and placing operations appropriately across available processors. However, these optimizations depend on supported tensor shapes, data types, hardware capabilities, and runtime configuration, making empirical benchmarking essential before selecting a deployment strategy. By evaluating operator-level execution together with batching, concurrency, and memory behavior, engineers can improve hardware utilization while avoiding configurations that appear efficient in isolation but increase end-to-end latency under realistic production workloads.
Key Takeaway
Hardware-aware inference optimization combines quantization, pruning, distillation, operator-level improvements, and suitable execution configurations to align model computation with the capabilities of the target hardware. Each technique introduces different trade-offs involving model quality, memory usage, latency, throughput, and implementation complexity, making empirical validation essential for identifying improvements that translate into real deployment benefits. By measuring optimized models under representative workloads and selecting configurations that satisfy explicit accuracy and resource constraints, engineering teams can improve inference efficiency without treating smaller models or fewer theoretical operations as automatic guarantees of better performance.
Conclusion: Designing Models for the Hardware That Executes Them
Hardware-aware machine learning changes how engineering teams approach model development by treating computational efficiency and deployment constraints as fundamental design considerations rather than problems to solve after training. Although model accuracy, parameter count, and theoretical operation counts provide useful information during development, they do not fully determine how efficiently a model will execute on a particular processor or accelerator. Real-world performance also depends on memory bandwidth, data movement, parallel execution, numerical precision, runtime optimization, and the workload characteristics of the target environment, making hardware selection and model architecture decisions closely interconnected.
Building efficient models therefore requires engineers to evaluate architecture, hardware, and inference software as a coordinated system. Model depth and width influence computational parallelism, while operator selection, tensor dimensions, and numerical formats determine how effectively the model maps to available execution kernels. Techniques such as quantization, pruning, and knowledge distillation can reduce memory and computational requirements, but their benefits depend on whether the target hardware can exploit the resulting changes efficiently. A model with fewer parameters or fewer theoretical operations is not automatically faster, making direct measurement an essential part of architectural and optimization decisions.
Production deployment introduces additional considerations because hardware-aware models must operate under realistic request patterns, resource constraints, and service-level objectives. Cloud inference services may prioritize throughput and cost per prediction, interactive applications often emphasize predictable response times, and edge devices may require strict limits on memory usage, energy consumption, and thermal output. These different operating environments require engineers to select appropriate model architectures, runtime configurations, batch sizes, and computational resources according to measurable application requirements rather than assuming that one configuration will perform equally well everywhere.
Reliable optimization also requires a disciplined evaluation process that measures predictive quality alongside latency, throughput, memory consumption, and energy usage where relevant. Reproducible benchmarks, realistic load tests, and production monitoring help teams determine whether improvements observed during development remain valid under actual deployment conditions, while version tracking allows them to associate performance changes with specific models, runtimes, and hardware configurations. By evaluating the complete inference workflow, engineers can distinguish model execution bottlenecks from data movement, preprocessing, resource contention, and other factors that may limit the effectiveness of a particular optimization.
Ultimately, hardware-aware machine learning is an engineering discipline centered on finding the most effective relationship between model capability and available computational resources. The best solution is not necessarily the most complex architecture or the smallest model, but the configuration that satisfies the application's predictive-quality requirements while meeting its performance, energy, memory, and cost constraints. By incorporating hardware characteristics into model design from the beginning and continually validating decisions against measured results, engineering teams can build machine learning systems that use compute efficiently, scale reliably, and remain practical to operate in production.
Frequently Asked Questions
1. What Is Hardware-Aware Machine Learning?
Hardware-aware machine learning is an approach to designing, selecting, and optimizing machine learning models with explicit consideration of the hardware on which they will execute. Instead of optimizing model quality or theoretical computational complexity in isolation, engineers evaluate how architecture, numerical precision, memory requirements, and computational operations interact with target processors to determine actual inference speed, throughput, energy consumption, and deployment cost.
2. Why Is Hardware-Aware Model Design Important?
Hardware-aware model design is important because a model that performs well during development may execute inefficiently on the intended production hardware, particularly when its operations are poorly supported by the available runtime or require substantial data movement. Considering hardware constraints early helps engineering teams select architectures that meet application requirements without unnecessary computational overhead, reducing the risk of deploying models that are too slow, memory-intensive, or expensive for their operating environment.
3. What Is the Difference Between Theoretical FLOPs and Actual Model Performance?
Floating-point operations, or FLOPs, estimate the amount of arithmetic computation required by a model, while actual model performance depends on how efficiently that work executes on the target system. Memory bandwidth, processor utilization, kernel-launch overhead, parallelism, data transfers, and runtime implementation can all affect measured latency and throughput, meaning that two models with similar FLOP counts may exhibit substantially different performance in production.
4. How Do CPUs and GPUs Differ for Machine Learning Inference?
CPUs provide flexible execution and can be effective for lightweight models, small batches, and workloads that do not expose substantial parallelism, while GPUs are designed to execute large numbers of parallel operations and are often well suited to computationally intensive neural networks. The better choice depends on model architecture, request volume, batch size, memory requirements, software support, and latency objectives, so engineers should benchmark both options when the workload and deployment constraints justify the comparison.
5. What Role Does Memory Bandwidth Play in Model Performance?
Memory bandwidth determines how quickly data can move between memory and processing units, making it an important factor when inference requires frequent access to model parameters, intermediate activations, or large embedding tables. A model can remain slow despite having sufficient computational capacity if its execution repeatedly waits for data, so reducing unnecessary memory transfers, reusing intermediate results, and selecting efficient tensor representations can improve performance when data movement is the primary bottleneck.
6. What Is Hardware-Aware Neural Architecture Search?
Hardware-aware neural architecture search evaluates candidate model architectures according to both predictive performance and hardware-related objectives, such as inference latency, memory consumption, energy usage, or throughput. The search process can explore model depth, width, operator choices, tensor dimensions, and other architectural parameters, using measured performance or predictive estimates to identify configurations that satisfy deployment constraints before validating promising candidates on the actual target hardware.
7. How Does Quantization Improve Machine Learning Efficiency?
Quantization represents model parameters and, where supported, intermediate computations using lower numerical precision, potentially reducing model size, memory traffic, and computational cost. Its effectiveness depends on the target hardware and runtime because lower-precision operations must be supported efficiently to deliver meaningful speed improvements, while the resulting numerical approximation must be evaluated against the application's prediction-quality requirements to ensure that the optimized model remains suitable for deployment.
8. What Is the Difference Between Pruning and Quantization?
Pruning reduces model complexity by removing selected parameters, connections, channels, or structures, whereas quantization reduces the precision used to represent model values. Both techniques can improve efficiency, but their practical benefits depend on hardware and runtime support, since sparse models may require specialized kernels to exploit reduced computation while lower-precision models need efficient numerical execution to realize their potential speed and memory advantages.
9. How Does Knowledge Distillation Help With Hardware-Constrained Deployment?
Knowledge distillation trains a smaller student model to reproduce useful behavior learned by a larger teacher model, potentially allowing the student to deliver competitive predictive performance with fewer parameters and lower computational requirements. This approach can be valuable for mobile devices, edge deployments, and high-volume inference services, although the quality of the student model depends on the training data, distillation strategy, and architecture selected for the intended hardware.
10. Does a Smaller Model Always Run Faster?
A smaller model does not always execute faster because parameter count alone does not describe how efficiently its operations map to the target processor or inference runtime. A compact architecture may rely on poorly optimized operators or irregular memory-access patterns, while a somewhat larger model may use hardware-friendly matrix operations and optimized kernels, making measured latency, throughput, and memory behavior more reliable indicators of practical efficiency than model size alone.
11. How Should Engineers Benchmark Hardware-Aware Models?
Engineers should benchmark candidate models on the intended hardware using representative inputs, realistic batch sizes, suitable concurrency levels, and a consistent runtime configuration. Measurements should include latency percentiles, throughput, peak memory consumption, processor utilization, and energy usage where relevant, while the same experiments should evaluate prediction quality so that performance improvements can be compared against the actual accuracy and operating requirements of the application.
12. How Can Hardware-Aware Machine Learning Reduce Energy Consumption?
Hardware-aware machine learning can reduce energy consumption by selecting efficient model architectures, limiting unnecessary computation, reducing memory transfers, and using numerical formats and execution kernels that the target hardware handles efficiently. Techniques such as quantization, suitable batching, model compression, and resource-aware execution can contribute to lower energy use, although the actual benefit depends on workload characteristics, hardware utilization, runtime behavior, and whether the optimization reduces total energy required to produce a useful prediction.
13. How Does Hardware-Aware ML Apply to Edge Devices?
Edge devices often impose strict limits on memory, processing capacity, power consumption, and thermal output, making hardware-aware model design particularly important for local inference. Engineers may use compact architectures, quantization, distillation, and optimized inference runtimes to fit models within these constraints while maintaining acceptable accuracy and response times, with deployment testing needed to verify that the model performs reliably under the device's actual operating conditions.
14. What Is the Difference Between Hardware-Aware Training and Hardware-Aware Inference Optimization?
Hardware-aware training incorporates deployment considerations into the model development process, potentially influencing architecture selection, numerical precision, or optimization objectives before the final model is produced. Hardware-aware inference optimization focuses on improving the execution of an existing model through techniques such as quantization, operator fusion, runtime configuration, batching, and resource allocation, although the two approaches often complement one another when a model must satisfy strict production constraints.
15. What Are the Best Practices for Deploying Hardware-Aware ML Models in Production?
Successful deployment begins with defining measurable requirements for prediction quality, latency, throughput, memory usage, energy consumption, and operating cost, followed by selecting and benchmarking candidate models on the intended hardware. Engineering teams should preserve reproducible model and runtime configurations, test realistic workloads, monitor production performance, and re-evaluate the model when hardware, software dependencies, or workload characteristics change, ensuring that hardware-specific optimizations continue to deliver measurable benefits without compromising predictive reliability.