به صورت خلاصه از اولین callback آن فعلا صرفنظر کنید. مابقی درست است.
نمایش متن در زیر جدول مربوط به هر گروه
به صورت خلاصه از اولین callback آن فعلا صرفنظر کنید. مابقی درست است.
var list2 = context.Products .OrderBy(one => one.ProductNumber) .Where(x => x.IsActive == isActive && x.ProductName == name);
/** * * <p> * check network is available or not <br/> * internet connection is not matter,for check internet connection refer to IsInternetConnected() Method in this class * </p> * <p> * Required Permission : <b>android.permission.ACCESS_NETWORK_STATE</b> * </p> * @param context * @return returns true if a network is available */ public boolean isNetworkAvailable(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null && activeNetworkInfo.isConnected(); }
public class ProjectSettings { public static NotificationsId=new NotificationsId(); public static UrlAddresss=new UrlAddresss(); public static SdPath=new SdPath(); ...... }
ProjectSettings.NotificationsId.UpdateNotificationId
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
public interface IMessageUI { void ShowToast(Context context,String message); } public class MessageUI impelement IMessageUI { public void ShowToast(Context context,string message) { Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } }
<receiver android:name=".AppStartReceiver" android:enabled="true"> <intent-filter> <action android:name="org.telegram.start" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
public class AppStartReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { ApplicationLoader.startPushService(); } }); } }
<receiver android:name=".MusicPlayerReceiver" > <intent-filter> <action android:name="org.telegram.android.musicplayer.close" /> <action android:name="org.telegram.android.musicplayer.pause" /> <action android:name="org.telegram.android.musicplayer.next" /> <action android:name="org.telegram.android.musicplayer.play" /> <action android:name="org.telegram.android.musicplayer.previous" /> <action android:name="android.intent.action.MEDIA_BUTTON" /> <action android:name="android.media.AUDIO_BECOMING_NOISY" /> </intent-filter> </receiver>
From query= new Select() .from(Poem.class) .innerJoin(BankPoemsGroups.class) .on("poems.id=bank_poems_groups.poem") .where("BankGroup=?", String.valueOf(groupId)); return query.execute();
@Table(name="poems") public class Poem extends Model { public static String tableName="poems"; public static String codeColumn="code"; public static String titleColumn="title"; public static String bookColumn="book"; ...... @Column(name="code",index = true) public int Code; @Column(name="title") public String Title; @Column(name="book") public Book Book; .....}
From query= new Select() .from(Poem.class) .innerJoin(BankPoemsGroups.class) .on(Poem.TableName+"."+ Poem.IdColumn+"="+ BankPoemsGroups.TableName+"."+ BankPoemsGroups.PoemColumn) .where(Poem.BankGroupColumn+"=?", String.valueOf(groupId)); return query.execute();
public class QueryConcater { public String GetInnerJoinQuery(String table1,String field1,String table2,String field2) { String query=table1 +"." +field1+"="+table2+"."+field2; return query; } ...... }
return new Select() .from(Color.class) .innerJoin(ProductItem.class) .on(queryConcater.GetInnerJoinQuery(ProductItem.TableName, ProductItem.ColorColumn, Color.TableName)) .where(queryConcater.WhereConditionQuery (ProductItem.TableName, ProductItem.ProductColumn), productId) .execute();
ACRA.getErrorReporter().handleException(caughtException);
public void CopyFile(String source,String destination,CopyFileListener copyFileListener) { try { InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(destination); long fileLength=new File(source).length(); // Transfer bytes from in to out byte[] buf = new byte[64*1024]; int len; long total=0; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); total+=len; copyFileListener.PublishProgress(fileLength,total); } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } }
public void CopyFile(String source,String destination,CopyFileListener copyFileListener) throws IOException { InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(destination); long fileLength=new File(source).length(); // Transfer bytes from in to out byte[] buf = new byte[64*1024]; int len; long total=0; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); total+=len; copyFileListener.PublishProgress(fileLength,total); } in.close(); out.close(); }
<form method="post" asp-action="Index" asp-controller="TestFileUpload" enctype="multipart/form-data"> <input type="file" name="files" multiple /> <input type="submit" value="Upload" /> </form>
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Index(IList<IFormFile> files)
public class TestFileUploadController : Controller { private readonly IHostingEnvironment _environment; public TestFileUploadController(IHostingEnvironment environment) { _environment = environment; }
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Index(IList<IFormFile> files) { var uploadsRootFolder = Path.Combine(_environment.WebRootPath, "uploads"); if (!Directory.Exists(uploadsRootFolder)) { Directory.CreateDirectory(uploadsRootFolder); } foreach (var file in files) { if (file == null || file.Length == 0) { continue; } var filePath = Path.Combine(uploadsRootFolder, file.FileName); using (var fileStream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(fileStream).ConfigureAwait(false); } } return View(); }
public class UserViewModel { [Required(ErrorMessage = "Please select a file.")] [DataType(DataType.Upload)] public IFormFile Photo { get; set; } }
@model UserViewModel <form method="post" asp-action="UploadPhoto" asp-controller="TestFileUpload" enctype="multipart/form-data"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <input asp-for="Photo" /> <span asp-validation-for="Photo" class="text-danger"></span> <input type="submit" value="Upload"/> </form>
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> UploadPhoto(UserViewModel userViewModel) { if (ModelState.IsValid) { var formFile = userViewModel.Photo; if (formFile == null || formFile.Length == 0) { ModelState.AddModelError("", "Uploaded file is empty or null."); return View(viewName: "Index"); } var uploadsRootFolder = Path.Combine(_environment.WebRootPath, "uploads"); if (!Directory.Exists(uploadsRootFolder)) { Directory.CreateDirectory(uploadsRootFolder); } var filePath = Path.Combine(uploadsRootFolder, formFile.FileName); using (var fileStream = new FileStream(filePath, FileMode.Create)) { await formFile.CopyToAsync(fileStream).ConfigureAwait(false); } RedirectToAction("Index"); } return View(viewName: "Index"); }
[FileExtensions(Extensions = ".png,.jpg,.jpeg,.gif", ErrorMessage = "Please upload an image file.")]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class UploadFileExtensionsAttribute : ValidationAttribute { private readonly IList<string> _allowedExtensions; public UploadFileExtensionsAttribute(string fileExtensions) { _allowedExtensions = fileExtensions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } public override bool IsValid(object value) { var file = value as IFormFile; if (file != null) { return isValidFile(file); } var files = value as IList<IFormFile>; if (files == null) { return false; } foreach (var postedFile in files) { if (!isValidFile(postedFile)) return false; } return true; } private bool isValidFile(IFormFile file) { if (file == null || file.Length == 0) { return false; } var fileExtension = Path.GetExtension(file.FileName); return !string.IsNullOrWhiteSpace(fileExtension) && _allowedExtensions.Any(ext => fileExtension.Equals(ext, StringComparison.OrdinalIgnoreCase)); } }
public class UserViewModel { [Required(ErrorMessage = "Please select a file.")] //`FileExtensions` needs to be applied to a string property. It doesn't work on IFormFile properties, and definitely not on IEnumerable<IFormFile> properties. //[FileExtensions(Extensions = ".png,.jpg,.jpeg,.gif", ErrorMessage = "Please upload an image file.")] [UploadFileExtensions(".png,.jpg,.jpeg,.gif", ErrorMessage = "Please upload an image file.")] [DataType(DataType.Upload)] public IFormFile Photo { get; set; } }
<Window x:Class="TwoViews.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MVVM Light View Switching" d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding Main, Source={StaticResource Locator}}" ResizeMode="NoResize" SizeToContent="WidthAndHeight" mc:Ignorable="d"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ContentControl Content="{Binding CurrentViewModel}" /> <DockPanel Grid.Row="1" Margin="5"> <Button Width="75" Height="23" Command="{Binding SecondViewCommand}" Content="Second View" DockPanel.Dock="Right" /> <Button Width="75" Height="23" Command="{Binding FirstViewCommand}" Content="First View" DockPanel.Dock="Left" /> </DockPanel> </Grid> </Window>
/// This is our MainViewModel that is tied to the MainWindow via the /// ViewModelLocator class. /// </summary> public class MainViewModel : ViewModelBase { /// <summary> /// Static instance of one of the ViewModels. /// </summary> private static readonly SecondViewModel SecondViewModel = new SecondViewModel(); /// <summary> /// Static instance of one of the ViewModels. /// </summary> private static readonly FirstViewModel FirstViewModel = new FirstViewModel(); /// <summary> /// The current view. /// </summary> private ViewModelBase _currentViewModel; /// <summary> /// Default constructor. We set the initial view-model to 'FirstViewModel'. /// We also associate the commands with their execution actions. /// </summary> public MainViewModel() { CurrentViewModel = FirstViewModel; FirstViewCommand = new RelayCommand(ExecuteFirstViewCommand); SecondViewCommand = new RelayCommand(ExecuteSecondViewCommand); } /// <summary> /// The CurrentView property. The setter is private since only this /// class can change the view via a command. If the View is changed, /// we need to raise a property changed event (via INPC). /// </summary> public ViewModelBase CurrentViewModel { get { return _currentViewModel; } set { if (_currentViewModel == value) return; _currentViewModel = value; RaisePropertyChanged("CurrentViewModel"); } } /// <summary> /// Simple property to hold the 'FirstViewCommand' - when executed /// it will change the current view to the 'FirstView' /// </summary> public ICommand FirstViewCommand { get; private set; } /// <summary> /// Simple property to hold the 'SecondViewCommand' - when executed /// it will change the current view to the 'SecondView' /// </summary> public ICommand SecondViewCommand { get; private set; } /// <summary> /// Set the CurrentViewModel to 'FirstViewModel' /// </summary> private void ExecuteFirstViewCommand() { CurrentViewModel = FirstViewModel; } /// <summary> /// Set the CurrentViewModel to 'SecondViewModel' /// </summary> private void ExecuteSecondViewCommand() { CurrentViewModel = SecondViewModel; } }
<Application.Resources> <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /> <!-- We define the data templates here so we can apply them across the entire application. The data template just says that if our data type is of a particular view-model type, then render the appropriate view. The framework takes care of this dynamically. Note that the DataContext for the underlying view is already set at this point, so the view (UserControl), doesn't need to have it's DataContext set directly. --> <DataTemplate DataType="{x:Type vm:SecondViewModel}"> <views:SecondView /> </DataTemplate> <DataTemplate DataType="{x:Type vm:FirstViewModel}"> <views:FirstView /> </DataTemplate> </Application.Resources>
<div class="container"> <div class="alert alert-info"> <h4> ایجاد فاصله بین ستونها </h4> </div> <div class="row"> <div class="col-lg-3 col-sm-4"> <div class="alert alert-danger" role="alert"> ستون اول </div> </div> <div class="col-lg-8 col-lg-offset-1 col-sm-7 col-sm-offset-1"> <div class="alert alert-success" role="alert"> ستون دوم </div> </div> </div> <!-- end row --> </div>
import React, { Component } from "react"; class TableHeader extends Component { raiseSort = path => { console.log("raiseSort", path); const sortColumn = { ...this.props.sortColumn }; if (sortColumn.path === path) { sortColumn.order = sortColumn.order === "asc" ? "desc" : "asc"; } else { sortColumn.path = path; sortColumn.order = "asc"; } this.props.onSort(sortColumn); }; render() { return ( <thead> <tr> {this.props.columns.map(column => ( <th onClick={() => this.raiseSort(column.path)}>{column.label}</th> ))} </tr> </thead> ); } } export default TableHeader;
import TableHeader from "./common/tableHeader";
columns = [ { path: "title", label: "Title" }, { path: "genre.name", label: "Genre" }, { path: "numberInStock", label: "Stock" }, { path: "dailyRentalRate", label: "Rate" }, {}, {} ];
render() { const { movies, onDelete, onLike, onSort, sortColumn } = this.props; return ( <table className="table"> <TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort} /> <tbody>
index.js:1375 Warning: Each child in a list should have a unique "key" prop. Check the render method of `TableHeader`. See https://fb.me/react-warning-keys for more information.
class MoviesTable extends Component { columns = [ { path: "title", label: "Title" }, { path: "genre.name", label: "Genre" }, { path: "numberInStock", label: "Stock" }, { path: "dailyRentalRate", label: "Rate" }, { key: "like" }, { key: "delete" } ];
render() { return ( <thead> <tr> {this.props.columns.map(column => ( <th key={column.path || column.key} style={{ cursor: "pointer" }} onClick={() => this.raiseSort(column.path)} > {column.label} </th> ))} </tr> </thead> );
import React, { Component } from "react"; class TableBody extends Component { render() { const { data, columns } = this.props; return ( <tbody> {data.map(item => ( <tr> {columns.map(column => ( <td></td> ))} </tr> ))} </tbody> ); } } export default TableBody;
{movies.map(movie => ( <tr key={movie._id}> <td>{movie.title}</td>
<td>{item[column.path]}</td>
getPropValue(obj, path) { if (!path) { return obj; } const properties = path.split("."); return this.getPropValue(obj[properties.shift()], properties.join(".")); }
<td>{getPropValue(item, column.path)}</td>
class MoviesTable extends Component { columns = [ { path: "title", label: "Title" }, { path: "genre.name", label: "Genre" }, { path: "numberInStock", label: "Stock" }, { path: "dailyRentalRate", label: "Rate" }, { key: "like", content: movie => ( <Like liked={movie.liked} onClick={() => this.props.onLike(movie)} /> ) }, { key: "delete", content: movie => ( <button onClick={() => this.props.onDelete(movie)} className="btn btn-danger btn-sm" > Delete </button> ) } ];
renderCell = (item, column) => { if (column.content) { return column.content(item); } return this.getPropValue(item, column.path); }; createKey = (item, column) => { return item._id + (column.path || column.key); }; render() { const { data, columns } = this.props; return ( <tbody> {data.map(item => ( <tr key={item._id}> {columns.map(column => ( <td key={this.createKey(item, column)}> {this.renderCell(item, column)} </td> ))} </tr> ))} </tbody> ); }
//... import TableBody from "./common/tableBody"; //... class MoviesTable extends Component { // ... render() { const { movies, onSort, sortColumn } = this.props; return ( <table className="table"> <TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort} /> <TableBody columns={this.columns} data={movies} /> </table> ); } }
renderSortIcon = column => { const { sortColumn } = this.props; if (column.path !== sortColumn.path) { return null; } if (sortColumn.order === "asc") { return <i className="fa fa-sort-asc" />; } return <i className="fa fa-sort-desc" />; };
{column.label} {this.renderSortIcon(column)}
import TableBody from "./tableBody"; import TableHeader from "./tableHeader";
import TableBody from "./tableBody"; import TableHeader from "./tableHeader"; class Table extends Component { render() { const { columns, sortColumn, onSort, data } = this.props; return ( <table className="table"> <TableHeader columns={columns} sortColumn={sortColumn} onSort={onSort} /> <TableBody columns={columns} data={data} /> </table> ); } } export default Table;
//... import Table from "./common/table"; class MoviesTable extends Component { //... render() { const { movies, onSort, sortColumn } = this.props; return ( <Table columns={this.columns} sortColumn={sortColumn} onSort={onSort} data={movies} /> ); } }
در صورتی که ویژوال استودیوی شما دارای این ورژن و آپدیت نبود، میتوانید چارچوب دات نت 4.6.1 را جداگانه در سیستم خود نصب نمایید. توجه داشته باشید که برای استفاده از چارچوب دات نت در ویژوال استودیو باید نسخههای DevPack یا DeveloperPack را نصب نمایید (دریافت دات نت 4.6.1 نسخه مخصوص استفاده در ویژال استودیو).
در پروژه ایجاد شده فایلی به نام Program.cs و در آن کلاس Program وجود دارد. در این کلاس تابع شروع کننده برنامه یعنی Main وجود دارد و برنامه از این تابع شروع خواهد شد.
نمایی از فایلهای پروژه
در تابع شروع کننده برنامه ابتدا وضعیت پشتیبانی از SIMD را چک میکنیم. این کار را همانطور که قبلا در مقاله پیشنیاز توضیح داده شده است با استفاده از خاصیت Vector.IsHardwareAccelerated بررسی میکنیم. اگر مقدار آن برابر با False باشد به معنای عدم پشتیبانی میباشد و با بررسی این موضوع در اول برنامه، در صورت عدم پشتیبانی از SIMD به اجرای ادامهی برنامه خاتمه میدهیم.
پس از بررسی وضعیت پشتیبانی از SIMD ، تابعی را که در فایل Utilities.cs نوشته شده است، فراخوانی میکنیم. این تابع به بررسی وضعیت تعداد رجیسترهای SIMD و وضعیت انواع نوعهای دادهای در SIMD میپردازد. اگر هر نوع دادهای از SIMD پشتیبانی کند (که بستگی به نوع پردازنده شما دارد) اندازه هر نوع دادهای را در SIMD چاپ میکند و در صورت عدم پشتیبانی هر نوع دادهای از SIMD مقدار «عدم پشتیبانی SIMD از آن نوع دادهای» چاپ خواهد شد.
using System.Numerics; using static System.Console; namespace TestSIMD { class Program { private const int ArraySize = 7680 * 4320; static void Main(string[] args) { // بررسی وضعیت پشتیبانی از SIMD if (!Vector.IsHardwareAccelerated) { WriteLine("Hardware acceleration not supported."); WriteLine(); return; // عدم پشتیبانی و خاتمه برنامه } WriteLine("Hardware acceleration is supported"); // اعلام پشتیبانی از SIMD WriteLine(); // بررسی وضعیت نوعهای داده ای در مشخصات سخت افزاری SIMD Utilities.PrintHardwareSpecificSimdEffectiveness(); //به منظور عدم خروج از برنامه و دیدن نتایج آزمایش WriteLine("Press any key to exit"); ReadKey(); } } }
public static void TestIntArrayAdditionFunctions(int testSetSize) { WriteLine(); Write("Testing int array addition, generating test data..."); var intsOne = GetRandomIntArray(testSetSize); //تولید آرایه عددی به صورت تصادفی var intsTwo = GetRandomIntArray(testSetSize); WriteLine($" done, testing...");// پایان تولید آرایهها و شروع پردازش var naiveTimesMs = new List<long>(); // تعریف لیستی برای ریختن زمان پاسخ دهی در حالت ساده و معمولی var hwTimesMs = new List<long>(); // تعریف لیستی برای ریختن زمان پاسخ دهی در حالت SIMD و سخت افزاری for (var i = 0; i < 3; i++) { // ایجاد حلقه برای تکرار محاسبات برای اندازه گیری زمان در حالت تکراری stopwatch.Restart();//شروع ثبت زمان var result = IntSimdProcessor.NaiveSumFunc(intsOne, intsTwo);//اجرای تابع جمع دو آرایه var naiveTimeMs = stopwatch.ElapsedMilliseconds;//ثبت زمان naiveTimesMs.Add(naiveTimeMs);//افزودن زمان ثبت شده به لیست زمانهای ساده و معمول WriteLine($"Naive analysis took: {naiveTimeMs}ms (last value = {result.Last()})."); stopwatch.Restart();//شروع ثبت زمان result = IntSimdProcessor.HWAcceleratedSumFunc(intsOne, intsTwo);//اجرای تابع جمع دو آرایه در حالت سخت افزاری var hwTimeMs = stopwatch.ElapsedMilliseconds;//ثبت زمان hwTimesMs.Add(hwTimeMs);//افزودن زمان به لیست زمانهای سخت افزاری WriteLine($"Hareware accelerated analysis took: {hwTimeMs}ms (last value = {result.Last()})."); }//پایان حلقه و چاپ نتایج WriteLine("Int array addition:"); WriteLine($"Naive method average time: {naiveTimesMs.Average():.##}"); WriteLine($"HW accelerated method average time: {hwTimesMs.Average():.##}"); WriteLine($"Hardware speedup: {naiveTimesMs.Average() / hwTimesMs.Average():P}%"); }
نام تابع ذکر شده نشان دهنده آزمایش بر روی آرایه اعداد صحیح یا همان Integer میباشد که شامل یک پارامتر ورودی از نوع عدد صحیح میباشد. این پارامتر ورودی نشان دهنده اندازه هر آرایهای میباشد که قرار است تولید شود.
TestIntArrayAdditionFunctions(int testSetSize)
در قدم اول این تابع، باید آرایهها را تولید کنیم که کد آن به صورت زیر است.
Write("Testing int array addition, generating test data..."); var intsOne = GetRandomIntArray(testSetSize); var intsTwo = GetRandomIntArray(testSetSize); WriteLine($" done, testing...");
ابتدا در خروجی چاپ میکنیم که در حال ایجاد دادههای مربوط به آزمایش هستیم و سپس با استفاده از تابع GetRandomIntArray آرایهای را ایجاد میکنیم و در متغیرهای مربوطه میریزیم. این تابع دارای یک پارامتر ورودی از نوع عدد صحیح است که آرایهای را به طول پارامتر ورودی تولید میکند. این تابع در فایل Utilities.cs قرار دارد.
در پایان تولید آرایهها، اتمام تولید و ایجاد آرایهها را با چاپ در خروجی اعلام میکنیم.
سپس با معرفی دو لیست زیر میتوانیم زمانهای اجرا را در آنها بریزیم و در پایان، تابع میانگین این زمانها را محاسبه و چاپ کنیم. لیست اول برای نگهداری زمانهای اجرای عملیات در حالت معمولی و لیست دوم برای نگهداری زمانهای اجرای عملیات در حالت SIMD میباشد.
var naiveTimesMs = new List<long>(); var hwTimesMs = new List<long>();
سپس با ایجاد حلقه ای از 0 تا 3 که در کل 3 مرتبه اجرا میشود عملیات را تکرار و زمان آن را ثبت میکنیم.
for (var i = 0; i < 3; i++)
درون حلقه یک عملیات را در دوحالت معمولی یا ساده و SIMD اجرا میکنیم. قبل از اجرای عملیات اول ابتدا stopwatch را ریست میکنیم. با این کار زمان صفر شده و شروع به اندازه گیری میکند. سپس عملیات مربوط به جمع دو آرایه را در حالت معمولی که در فایل IntSimdProcessor.cs قرار دارد، فراخوانی میکنیم. پس از اجرای این عملیات مقدار stopwatch را به میلی ثانیه در یک متغیر ذخیره میکنیم و این مقدار را به لیست زمانهای اجرای معمولی اضافه میکنیم. در نهایت نتیجه زمان اجرا را در خروجی چاپ میکنیم.
stopwatch.Restart(); var result = IntSimdProcessor.NaiveSumFunc(intsOne, intsTwo); var naiveTimeMs = stopwatch.ElapsedMilliseconds; naiveTimesMs.Add(naiveTimeMs); WriteLine($"Naive analysis took: {naiveTimeMs}ms (last value = {result.Last()}).");
پس از اجرای عملیات در حالت ساده یا معمولی، حال نوبت همان عملیات در حالت SIMD میباشد. دوباره stopwatch را ریست میکنیم و عملیات در SIMD را اجرا کرده و بعد از آن مقدار stopwatch را درون متغیری میریزیم و آن را به لیست زمانهای اجرای عملیات در SIMD اضافه میکنیم و در نهایت نتیجه زمان اجرا را در خروجی چاپ میکنیم.
stopwatch.Restart(); result = IntSimdProcessor.HWAcceleratedSumFunc(intsOne, intsTwo); var hwTimeMs = stopwatch.ElapsedMilliseconds; hwTimesMs.Add(hwTimeMs); WriteLine($"Hareware accelerated analysis took: {hwTimeMs}ms (last value = {result.Last()}).");
پس از اجرای حلقه، حال نوبت به نمایش نتیجه میانگین زمانها در خروجی است. ابتدا میانگین زمانهای اجرا در حالت ساده یا معمولی را که به میلی ثانیه است را در خروجی چاپ میکنیم. بعد از آن میانگین زمانهای اجرا در حالت SIMD را در خروجی چاپ میکنیم و در آخر سرعت زمان اجرا در حالت SIMD را نسبت به حالت معمولی به درصد چاپ میکنیم.
WriteLine($"Naive method average time: {naiveTimesMs.Average():.##}"); WriteLine($"HW accelerated method average time: {hwTimesMs.Average():.##}"); WriteLine($"Hardware speedup: {naiveTimesMs.Average() / hwTimesMs.Average():P}%");
در این مقاله تنها به توضیحی در مورد این آزمایش اکتفا میکنیم. لازم به ذکر است که دیگر آزمایشها نیز دقیقا ساختاری مشابه این آزمایش را دارند و تنها عملیات اجرا در آنها متفاوت است. در کلاس PerformanceTests توضیحات لازم مربوط به هر آزمایش و تابع داده شده است و میتوانید با مراجعه به کد برنامه آنها را مورد بررسی قرار دهید.
برای اجرای تمامی آزمایشها، کلیه توابع نوشته شده در کلاس PerformanceTests را در کلاس Program و در تابع Main که تابع شروع کننده برنامه میباشد، پس از بررسی وضعیت نوعهای دادهای قرار میدهیم.
تصویر مربوط به اجرای کامل برنامه را میتوانید مشاهده میکنید.
این جدول بر اساس یک بار اجرای برنامه در سیستم من ترسیم شده است و اجرای برنامه در سیستمهای مختلف خروجیهای متفاوتی را دارد. لازم به ذکر است که اندازه آرایهها بسیار بزرگ است و این نتایج با آرایههایی به طول بیش از هزاران هزار عنصر میباشد.
زمانها در جدول به میلی ثانیه میباشد.
ردیف | عملیات | دور اول | دور دوم | دور سوم | میانگین حالت ساده | میانگین حالت SIMD | |||
درحالت ساده | درحالت SIMD | درحالت ساده | درحالت SIMD | درحالت ساده | درحالت SIMD | ||||
1 | جمع دو آرایه با استفاده از یک آرایه کمکی در اعداد صحیح | 157 | 131 | 128 | 131 | 128 | 138 | 137.67 | 133.33 |
2 | جمع دو آرایه بدون استفاده از آرایه کمکی در اعداد float | 122 | 133 | 99 | 99 | 99 | 93 | 106.67 | 108.33 |
3 | جمع دو آرایه بدون استفاده از آرایه کمکی در اعداد صحیح | 83 | 73 | 86 | 88 | 78 | 81 | 82.33 | 80.67 |
4 | جمع دو آرایه اول ورودی - مجموع در آرایه سوم ریخته میشود - در اعداد صحیح کوچک بدون علامت | 58 | 63 | 50 | 48 | 58 | 46 | 55.33 | 52.33 |
5 | جمع دو آرایه بدون استفاده از آرایه کمکی در اعداد صحیح کوچک بدون علامت | 55 | 40 | 53 | 36 | 53 | 46 | 53.67 | 40.67 |
6 | بدست آوردن کمترین و بیشترین مقدار در یک آرایه اعداد صحیح | 91 | 36 | 91 | 39 | 90.67 | 38 | 90.66 | 38 |
7 | بدست آوردن کمترین و بیشترین مقدار در یک آرایه اعداد صحیح کوچک بدون علامت | 90 | 20 | 89 | 19 | 88 | 18 | 89 | 19 |
8 | جمع عناصر آرایه ورودی و ذخیره مجموع آنها در یک متغیر کمکی | 33 | 309 | 32 | 263 | 31 | 291 | 32 | 287.67 |
9 | جمع عناصر آرایه ورودی و ذخیره مجموع آنها در یک متغیر کمکی بدون بررسی سرریز | 30 | 13 | 29 | 13 | 30 | 12 | 29.67 | 12.67 |
10 | محاسبه میانگین و بدست آوردن کمترین و بیشترین مقدار در آرایه اعداد صحیح کوچک بدون علامت | 89 | 50 | 90 | 51 | 90 | 49 | 89.57 | 50 |
public static class CurryMethodExtensions { public static Func< A, Func< B, Func< C, R > > > Curry< A, B, C, R >( this Func< A, B, C, R > f ) { return a => b => c => f( a, b, c ); } }
Func< int, int, int, int > addNumbers = ( x, y, z ) => x + y + z; var f1 = addNumbers.Curry(); Func< int, Func< int, int > > f2 = f1( 3 ); Func< int, int > f3 = f2( 4 ); Console.WriteLine( f3( 5 ) );
public static class CurryMethodExtensions { public static Func< C, R > Partial< A, B, C, R >( this Func< A, B, C, R > f, A a, B b ) { return c => f( a, b, c ); } }
Func< int, int, int, int > sumNumbers = ( x, y, z ) => x + y + z; Func< int, int > f4 = sumNumbers.Partial( 3, 4 ); Console.WriteLine( f4( 5 ) );
var obj = new WeakReferenceTest { FirstName = "Vahid" }; var w = new WeakReference(obj); obj = null; GC.Collect(); var weakReferenceTest = w.Target as WeakReferenceTest; if ( weakReferenceTest != null ) Console.WriteLine( weakReferenceTest.FirstName );
public abstract class ThreadSafeLazyBaseSingleton< T > where T : new() { static readonly Lazy< T > lazy = new Lazy< T >( () => new T() ); public static T Instance => lazy.Value; }
var positiveString = "91389681247993671255433422114345532000000"; var negativeString = "-9031583741089631207100208803453423537140000"; var posBigInt = BigInteger.Parse( positiveString ); Console.WriteLine( posBigInt ); var negBigInt = BigInteger.Parse( negativeString ); Console.WriteLine( negBigInt );